154 lines
4.8 KiB
C++
154 lines
4.8 KiB
C++
#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;
|
||
}
|