Hm3
This commit is contained in:
153
Exercise/Homework3/grok的表达式树模板.cpp
Normal file
153
Exercise/Homework3/grok的表达式树模板.cpp
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user