This commit is contained in:
e2hang
2025-10-24 09:52:24 +08:00
parent 5e189f9bb2
commit 218a2fb56a
8 changed files with 1011 additions and 0 deletions

View File

@@ -0,0 +1,153 @@
#include <iostream>
#include <memory>
#include <string>
#include <vector>
enum class NodeType {
OPERAND, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
OPERATOR // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
};
class ExprNode {
public:
NodeType node_type;
std::unique_ptr<ExprNode> left;
std::unique_ptr<ExprNode> right;
virtual ~ExprNode() = default;
virtual std::string toString() const = 0;
};
class OperandNode : public ExprNode {
public:
int value;
OperandNode(int val) : value(val) {
node_type = NodeType::OPERAND;
}
std::string toString() const override {
return "Operand(" + std::to_string(value) + ")";
}
};
class OperatorNode : public ExprNode {
public:
std::string op;
OperatorNode(const std::string& oper, std::unique_ptr<ExprNode> l = nullptr, std::unique_ptr<ExprNode> r = nullptr)
: op(oper) {
node_type = NodeType::OPERATOR;
left = std::move(l);
right = std::move(r);
}
std::string toString() const override {
std::string left_str = left ? " " + left->toString() : "";
std::string right_str = right ? " " + right->toString() : "";
return "Operator(" + op + left_str + right_str + ")";
}
};
class ExprTree {
private:
std::unique_ptr<ExprNode> root;
public:
ExprTree(std::unique_ptr<ExprNode> r = nullptr) : root(std::move(r)) {}
void setRoot(std::unique_ptr<ExprNode> r) {
root = std::move(r);
}
// ʾ<><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Inorder Traversal<61><6C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڴ<EFBFBD>ӡ<EFBFBD><D3A1><EFBFBD><EFBFBD>ʽ
void inorderTraversal(const std::unique_ptr<ExprNode>& node, std::vector<std::string>& result) const {
if (!node) return;
inorderTraversal(node->left, result);
if (node->node_type == NodeType::OPERAND) {
auto operand = static_cast<const OperandNode*>(node.get());
result.push_back(std::to_string(operand->value));
} else {
auto oper = static_cast<const OperatorNode*>(node.get());
result.push_back(oper->op);
}
inorderTraversal(node->right, result);
}
std::string toInfixString() const {
std::vector<std::string> result;
inorderTraversal(root, result);
if (result.empty()) return "";
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD><CAB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E8B4A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD><C8B7>ʾ<EFBFBD><CABE><EFBFBD>ȼ<EFBFBD>
std::string infix;
for (const auto& s : result) {
infix += s + " ";
}
return infix.substr(0, infix.size() - 1); // <20>Ƴ<EFBFBD>ĩβ<C4A9>ո<EFBFBD>
}
// ʾ<><CABE><EFBFBD><EFBFBD><EFBFBD>Ӽ<EFBFBD><D3BC><EFBFBD><EFBFBD><EFBFBD>׺<EFBFBD><D7BA><EFBFBD><EFBFBD>ʽ<EFBFBD><CABD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>򻯰棬<F2BBAFB0><E6A3AC>֧<EFBFBD>ֻ<EFBFBD><D6BB><EFBFBD> + - * / <20><><EFBFBD><EFBFBD><EFBFBD>ţ<EFBFBD>
// ע<><EFBFBD><E2A3BA><EFBFBD><EFBFBD>һ<EFBFBD><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʵ<EFBFBD>֣<EFBFBD>ʹ<EFBFBD>õݹ<C3B5><DDB9>½<EFBFBD><C2BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>չ<EFBFBD><D5B9><EFBFBD><EFBFBD>
static std::unique_ptr<ExprNode> buildFromInfix(const std::string& expr, size_t& pos) {
// <20><><EFBFBD><EFBFBD><EFBFBD>ո<EFBFBD>
while (pos < expr.size() && expr[pos] == ' ') ++pos;
if (pos >= expr.size()) return nullptr;
char ch = expr[pos];
if (isdigit(ch)) {
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
int num = 0;
while (pos < expr.size() && isdigit(expr[pos])) {
num = num * 10 + (expr[pos++] - '0');
}
return std::make_unique<OperandNode>(num);
} else if (ch == '(') {
++pos; // <20><><EFBFBD><EFBFBD> '('
auto left = buildFromInfix(expr, pos);
auto op_node_raw = buildFromInfix(expr, pos); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
auto right = buildFromInfix(expr, pos);
if (pos < expr.size() && expr[pos] == ')') ++pos;
if (op_node_raw && op_node_raw->node_type == NodeType::OPERATOR) {
auto op_node = std::unique_ptr<OperatorNode>(static_cast<OperatorNode*>(op_node_raw.release()));
op_node->left = std::move(left);
op_node->right = std::move(right);
return std::move(op_node);
}
return nullptr; // <20><><EFBFBD><EFBFBD>
} else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
std::string oper(1, expr[pos++]);
return std::make_unique<OperatorNode>(oper);
}
return nullptr;
}
// <20><><EFBFBD>ݷ<EFBFBD><DDB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
void buildFromInfix(const std::string& expr) {
size_t pos = 0;
root = buildFromInfix(expr, pos);
}
};
// ʾ<><CABE>ʹ<EFBFBD><CAB9>
int main() {
// <20>ֶ<EFBFBD><D6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>3 + (4 * 5)
auto mul = std::make_unique<OperatorNode>("*");
mul->left = std::make_unique<OperandNode>(4);
mul->right = std::make_unique<OperandNode>(5);
auto add = std::make_unique<OperatorNode>("+");
add->left = std::make_unique<OperandNode>(3);
add->right = std::move(mul);
ExprTree tree(std::move(add));
std::cout << "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ: " << tree.root->toString() << std::endl;
std::cout << "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>: " << tree.toInfixString() << std::endl; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> "3 + * 4 5"
// <20><><EFBFBD>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>򻯣<EFBFBD><F2BBAFA3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֧<EFBFBD>֣<EFBFBD>
ExprTree tree2;
tree2.buildFromInfix("3+(4*5)"); // <20><>Ҫ<EFBFBD><D2AA><EFBFBD>ƽ<EFBFBD><C6BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Դ<EFBFBD><D4B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ
std::cout << "<EFBFBD><EFBFBD><EFBFBD>ַ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: " << (tree2.root ? tree2.root->toString() : "<EFBFBD><EFBFBD>Ч") << std::endl;
return 0;
}