开始计概A下半学期。

This commit is contained in:
rogerwang2008 committed 2026-11-09 21:13:09 +08:00
1 parent 0cfdc8499c
commit 38e97654e1
31 files changed
+2144 -110

No files matched your search

@@ -0,0 +1,224 @@
#include <iostream>
#include <cassert>
#include <functional>
#include <stack>
#include <vector>
#include <unordered_map>
using Expression = std::string; // 没有数字
bool is_operator(const char c) {
return c == '+' || c == '-' || c == '*' || c == '/'
|| c == '(' || c == ')';
}
int get_priority(char c) {
assert(is_operator(c));
if (c == '+' || c == '-') { return 1; }
if (c == '*' || c == '/') { return 2; }
throw std::invalid_argument("Invalid operator!");
}
class ExpressionTree {
public:
struct Node {
char value;
int depth = -1;
Node *father = nullptr, *left = nullptr, *right = nullptr;
explicit Node(char c) : value(c) {}
[[nodiscard]] bool is_operator() const {
return ::is_operator(value);
}
[[nodiscard]] int get_priority() const {
return ::get_priority(value);
}
};
Node* root = nullptr;
int depth = -1;
void init_depths() {
dfs([this](Node* node, int dfs_depth) {
node->depth = dfs_depth;
depth = std::max(depth, dfs_depth);
});
depth++;
}
void init_with_infix(const Expression& expression) {
std::stack<Node*> ops;
std::stack<Node*> nums;
for (char c : expression) {
if (!is_operator(c)) {
nums.push(new Node(c));
continue;
}
if (c == '(') {
ops.push(new Node(c));
continue;
}
if (c == ')') {
while (ops.top()->value != '(') {
construct_one_op(ops, nums);
}
ops.pop();
continue;
}
Node* node = new Node(c);
while (!ops.empty() && ops.top()->value != '('
&& node->get_priority() <= ops.top()->get_priority()) {
construct_one_op(ops, nums);
}
ops.push(node);
}
while (!ops.empty()) {
construct_one_op(ops, nums);
}
root = nums.top();
init_depths();
}
protected:
static void construct_one_op(std::stack<Node*>& ops, std::stack<Node*>& nums) {
auto op = ops.top();
ops.pop();
auto num_right = nums.top();
nums.pop();
auto num_left = nums.top();
nums.pop();
op->left = num_left;
op->right = num_right;
num_left->father = op;
num_right->father = op;
nums.push(op);
}
public:
[[nodiscard]] Expression get_postfix() const {
Expression expression;
// 此代码正确,但是本人想试试 dfs
// std::stack<std::pair<Node*, short>> stack; // 0: 没干过活,1: 玩过左,2: 玩过右
// stack.emplace(root, 0);
// while (!stack.empty()) {
// // std::clog << "Top: " << stack.top().first->value << ", flag=" << stack.top().second << std::endl;
// if (stack.top().second == 0) {
// stack.top().second++;
// if (stack.top().first->left != nullptr) {
// stack.emplace(stack.top().first->left, 0);
// }
// } else if (stack.top().second == 1) {
// stack.top().second++;
// if (stack.top().first->right != nullptr) {
// stack.emplace(stack.top().first->right, 0);
// }
// } else {
// expression += stack.top().first->value;
// stack.pop();
// }
// }
dfs([&expression](Node* node, int _) {
expression.push_back(node->value);
}, 2);
return expression;
}
std::vector<std::string> get_string_lines() {
std::vector<std::string> lines(depth * 2);
dfs_with_id([&lines](Node* node, unsigned long long node_id) {
lines[node->depth * 2].resize(node_id, ' ');
lines[node->depth * 2][node_id - 1] = node->value;
if (node->left != nullptr) {
lines[node->depth * 2 + 1].resize(node_id - 1, ' ');
lines[node->depth * 2 + 1][node_id - 2] = '/';
}
if (node->right != nullptr) {
lines[node->depth * 2 + 1].resize(node_id + 1, ' ');
lines[node->depth * 2 + 1][node_id] = '\\';
}
}, 2);
lines.pop_back();
return lines;
}
long long calculate(const std::unordered_map<char, int>& variable_map, Node* node = nullptr) {
if (node == nullptr) { node = root; }
if (node->left == nullptr) { return variable_map.at(node->value); }
long long left = calculate(variable_map, node->left);
long long right = calculate(variable_map, node->right);
if (node->value == '+') { return left + right; }
if (node->value == '-') { return left - right; }
if (node->value == '*') { return left * right; }
if (node->value == '/') { return left / right; }
throw std::logic_error("");
}
protected:
void dfs(const std::function<void(Node*, int)>& func,
int func_entry = 0,
int dfs_depth = 0,
Node* node = nullptr) const {
if (dfs_depth == 0) { node = root; }
if (func_entry == 0) { func(node, dfs_depth); }
if (node->left != nullptr) { dfs(func, func_entry, dfs_depth + 1, node->left); }
if (func_entry == 1) { func(node, dfs_depth); }
if (node->right != nullptr) { dfs(func, func_entry, dfs_depth + 1, node->right); }
if (func_entry == 2) { func(node, dfs_depth); }
}
void dfs_with_id(const std::function<void(Node*, unsigned long long)>& func,
int func_entry = 0,
unsigned long long node_id = 0,
Node* node = nullptr) const {
if (node == nullptr) { node = root, node_id = 1 << (depth - 1); }
// std::clog << node_id << std::endl;
unsigned long long depth_bit = 1ull << (depth - node->depth - 1);
unsigned long long flipped_depth_bit = ~0ull ^ depth_bit;
if (func_entry == 0) { func(node, node_id); }
if (node->left != nullptr) {
dfs_with_id(func, func_entry, (node_id & flipped_depth_bit) | (depth_bit >> 1), node->left);
}
if (func_entry == 1) { func(node, node_id); }
if (node->right != nullptr) {
dfs_with_id(func, func_entry, node_id | (depth_bit >> 1), node->right);
}
if (func_entry == 2) { func(node, node_id); }
}
friend std::ostream& operator<<(std::ostream& os, ExpressionTree expression_tree) {
for (const auto& line : expression_tree.get_string_lines()) {
os << line << std::endl;
}
return os;
}
};
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
Expression infix_expression;
std::cin >> infix_expression;
ExpressionTree expression_tree;
expression_tree.init_with_infix(infix_expression);
std::cout << expression_tree.get_postfix() << std::endl;
std::cout << expression_tree;
int n;
std::cin >> n;
std::unordered_map<char, int> variable_map;
for (int i = 0; i < n; i++) {
char c;
int x;
std::cin >> c >> x;
variable_map[c] = x;
}
std::cout << expression_tree.calculate(variable_map) << std::endl;
return 0;
}
@@ -0,0 +1,107 @@
#include <functional>
#include <iostream>
#include <vector>
class BinaryTree {
public:
using NodeIdx = int;
struct Node {
char value;
NodeIdx left = -1, right = -1;
};
enum class FuncEntry { Pre, In, Post };
NodeIdx root = -1;
std::vector<Node> nodes;
void init_with_lines(const std::vector<std::string>& lines) {
nodes.reserve(lines.size());
std::vector<int> lines_dashes(lines.size());
int idx = 0;
root = init_with_lines(lines, 0, idx);
}
std::string prefix_traverse() {
std::string traverse;
traverse.reserve(nodes.size());
dfs([&traverse, this](NodeIdx node, int dfs_depth) {
traverse += nodes[node].value;
}, FuncEntry::Pre);
return traverse;
}
std::string infix_traverse() {
std::string traverse;
traverse.reserve(nodes.size());
dfs([&traverse, this](NodeIdx node, int dfs_depth) {
traverse += nodes[node].value;
}, FuncEntry::In);
return traverse;
}
std::string postfix_traverse() {
std::string traverse;
traverse.reserve(nodes.size());
dfs([&traverse, this](NodeIdx node, int dfs_depth) {
traverse += nodes[node].value;
}, FuncEntry::Post);
return traverse;
}
protected:
NodeIdx init_with_lines(const std::vector<std::string>& lines,
int depth, int& idx) {
if (idx >= lines.size() || lines[idx].size() - 1 < depth) { return -1; }
char value;
if ((value = lines[idx][lines[idx].size() - 1]) == '*') {
idx++;
return -1;
}
const NodeIdx node_idx = nodes.size();
nodes.push_back(Node{value});
idx++;
nodes[node_idx].left = init_with_lines(lines, depth + 1, idx);
nodes[node_idx].right = init_with_lines(lines, depth + 1, idx);
return node_idx;
}
void dfs(const std::function<void(NodeIdx, int)>& func,
FuncEntry func_entry = FuncEntry::Pre,
int dfs_depth = 0,
NodeIdx node = -1
) {
if (dfs_depth == 0) { node = root; }
if (func_entry == FuncEntry::Pre) { func(node, dfs_depth); }
if (nodes[node].left != -1) { dfs(func, func_entry, dfs_depth + 1, nodes[node].left); }
if (func_entry == FuncEntry::In) { func(node, dfs_depth); }
if (nodes[node].right != -1) { dfs(func, func_entry, dfs_depth + 1, nodes[node].right); }
if (func_entry == FuncEntry::Post) { func(node, dfs_depth); }
}
};
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
while (n--) {
std::vector<std::string> lines;
std::string s;
while (std::cin >> s && s != "0") {
lines.push_back(s);
}
BinaryTree binary_tree;
binary_tree.init_with_lines(lines);
std::cout << binary_tree.prefix_traverse() << std::endl
<< binary_tree.postfix_traverse() << std::endl
<< binary_tree.infix_traverse() << std::endl << std::endl;
}
return 0;
}
@@ -0,0 +1,112 @@
#include <functional>
#include <iostream>
#include <optional>
#include <queue>
#include <unordered_map>
#include <utility>
class HuffmanTree {
public:
struct Node {
long long weight;
std::optional<std::string> content;
Node *left = nullptr, *right = nullptr;
bool operator<(const Node& other) const {
return weight < other.weight;
}
};
enum class DfsEntries { Pre, In, Post };
Node* root = nullptr;
explicit HuffmanTree(const std::unordered_map<std::string, long long>& freq_map) {
std::priority_queue<Node*, std::vector<Node*>,
std::function<bool(Node*, Node*)>>
nodes_heap([](Node* a, Node* b) { return a->weight > b->weight; });
for (const auto& [key, freq] : freq_map) {
nodes_heap.push(new Node{.weight = freq, .content = key});
}
while (nodes_heap.size() > 1) {
Node* node1 = nodes_heap.top();
nodes_heap.pop();
Node* node2 = nodes_heap.top();
nodes_heap.pop();
Node* new_node = new Node{.weight = node1->weight + node2->weight, .left = node1, .right = node2};
nodes_heap.push(new_node);
}
root = nodes_heap.top();
}
std::unordered_map<std::string, std::vector<bool>> get_encodings() {
std::unordered_map<std::string, std::vector<bool>> encodings;
if (root->left == nullptr && root->right == nullptr) {
encodings[root->content.value()] = {false};
} else {
dfs_with_path([&encodings](Node* node, std::vector<bool> path) {
if (!node->content.has_value()) { return; }
encodings[node->content.value()] = std::move(path);
});
}
return encodings;
}
protected:
void dfs_with_path(const std::function<void(Node*, std::vector<bool>)>& func,
DfsEntries func_entry = DfsEntries::Pre) {
std::vector<bool> path;
dfs_with_path(func, func_entry, path);
}
void dfs_with_path(const std::function<void(Node*, std::vector<bool>)>& func,
DfsEntries func_entry,
std::vector<bool>& path,
Node* node = nullptr) {
if (node == nullptr) { node = root; }
if (func_entry == DfsEntries::Pre) { func(node, path); }
if (node->left != nullptr) {
path.push_back(false);
dfs_with_path(func, func_entry, path, node->left);
path.pop_back();
}
if (func_entry == DfsEntries::In) { func(node, path); }
if (node->right != nullptr) {
path.push_back(true);
dfs_with_path(func, func_entry, path, node->right);
path.pop_back();
}
if (func_entry == DfsEntries::Post) { func(node, path); }
}
};
std::ostream& operator<<(std::ostream& os, const std::vector<bool>& bintree_path) {
for (const auto bin : bintree_path) {
os << (bin ? 1 : 0);
}
return os;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<std::string> keys(n);
std::unordered_map<std::string, long long> freq_map;
for (int i = 0; i < n; i++) {
int freq;
std::cin >> keys[i] >> freq;
freq_map[keys[i]] = freq;
}
HuffmanTree huffman_tree(freq_map);
auto encodings = huffman_tree.get_encodings();
for (const auto& key : keys) {
std::cout << key << ' ' << encodings[key] << std::endl;
}
return 0;
}