Files
Data-Structure/Exercise/Homework3/grok的表达式树模板.cpp
e2hang 218a2fb56a Hm3
2025-10-24 09:52:24 +08:00

154 lines
4.8 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <iostream>
#include <memory>
#include <string>
#include <vector>
enum class NodeType {
OPERAND, // 操作数
OPERATOR // 运算符
};
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);
}
// 示例中序遍历Inorder Traversal用于打印表达式
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 "";
// 简化输出:实际中需处理括号以正确表示优先级
std::string infix;
for (const auto& s : result) {
infix += s + " ";
}
return infix.substr(0, infix.size() - 1); // 移除末尾空格
}
// 示例:从简单中缀表达式构建树(简化版,仅支持基本 + - * / 和括号)
// 注意:这是一个简化实现,使用递归下降解析器。你可以扩展它。
static std::unique_ptr<ExprNode> buildFromInfix(const std::string& expr, size_t& pos) {
// 跳过空格
while (pos < expr.size() && expr[pos] == ' ') ++pos;
if (pos >= expr.size()) return nullptr;
char ch = expr[pos];
if (isdigit(ch)) {
// 解析数字
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; // 跳过 '('
auto left = buildFromInfix(expr, pos);
auto op_node_raw = buildFromInfix(expr, pos); // 运算符
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; // 错误
} else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
std::string oper(1, expr[pos++]);
return std::make_unique<OperatorNode>(oper);
}
return nullptr;
}
// 便捷方法:从字符串构建树
void buildFromInfix(const std::string& expr) {
size_t pos = 0;
root = buildFromInfix(expr, pos);
}
};
// 示例使用
int main() {
// 手动构建树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 << "树表示: " << tree.root->toString() << std::endl;
std::cout << "中序: " << tree.toInfixString() << std::endl; // 输出如 "3 + * 4 5"
// 从字符串构建(简化,仅基本支持)
ExprTree tree2;
tree2.buildFromInfix("3+(4*5)"); // 需要完善解析器以处理完整表达式
std::cout << "从字符串构建: " << (tree2.root ? tree2.root->toString() : "无效") << std::endl;
return 0;
}