Stack & Binary Tree-Expression·Expression Tree·Expression Evaluation

Total time limit: 1000ms

Memory limit: 65535kB

description

As we all know, any expression can be represented by an expression tree. For example, the expression a+b*c can be expressed as the following expression tree:

   +
  / \
a   *
    / \
    b c

Now, give you an infix expression. This infix expression is represented by variables (without numbers). Please output this infix expression in the form of an expression binary tree.

enter

The input is divided into three parts.
The first part is a line, that is, the infix expression (the length is not greater than 50). The infix expression may contain lowercase letters to represent variables (az), and may also contain operators (+, -, *, /, parentheses), without numbers, or spaces.
The second part is an integer n (n <10), which represents the number of variables in the infix expression.
The third part has n lines, each line has the format C x, C is the character of the variable, and x is the value of the variable.

Output

The output is divided into three parts. The first part is the reverse Polish expression of the expression, which is the result of traversing the posterior root of the expression tree. Occupy one line.
The second part is the display of the expression tree, as shown in the sample output. If the binary tree is a full binary tree, the bottom leaf nodes occupy the 1, 3, 5, 7... positions of the abscissa respectively (the leftmost coordinate is 1), and then their parent nodes The abscissa is in the middle of the two child nodes. If the binary tree is not full, fill in spaces where there are no nodes (but please omit all spaces at the end of the line). Each line of parent node and child node is separated by one line, and slash (/) and backslash (\) are used to indicate the relationship of the tree. The abscissa position of / appears is one square to the left of the abscissa of the parent node, and the abscissa position that appears is one square to the right of the abscissa of the parent node. In other words, if the tree height is m, the output will have 2m-1 rows.
The third part is an integer, which represents the value of the infix expression after substituting the value into the variable. One thing to note is that division represents an arithmetic operation, that is, the part after the decimal point is discarded. At the same time, the test data guarantees that there will be no division by zero.

Sample input

a+b*c
3
a 2
b 7
c 5

Sample output

abc*+
   +
  / \
 a   *
    / \
    b c
37
#include <iostream>
#include <cstring>
#include <algorithm>
#include <stack>
#include <map>
#include <vector>
using namespace std;

map<char,int> priority = {
   
   {'+', 1}, {'-', 1}, {'*', 2}, {'/', 2}, {'(', 0}};
map<char,int> value;

struct node_t {
    char val;
    node_t *left;
    node_t *right;
    node_t(char val_, node_t *left_ = NULL, node_t *right_ = NULL) : val(val_), left(left_), right(right_) {}
};

stack<char> op;
stack<node_t*> expression;
inline void doit()
{
    node_t *b = expression.top(); expression.pop();
    node_t *a = expression.top(); expression.pop();
    node_t *c = new node_t(op.top(), a, b); op.pop();
    expression.push(c);
}
node_t *build_tree(char *in) {
    int l = strlen(in);
    for (int i = 0; i < l; ++i) {
        if (isalpha(in[i])) {
            expression.push(new node_t(in[i]));
        }
        else {
            if (in[i] == '(')
                op.push(in[i]);
            else if (in[i] == ')') {
                while (op.top() != '(')
                    doit();
                op.pop(); // for '('
            }
            else {
                while (!op.empty() && priority[op.top()] >= priority[in[i]])
                    doit();
                op.push(in[i]);
            }
        }
    }
    while (!op.empty()) {
        doit();
    }
    return expression.top();
}

void postfix_dfs(node_t *cur){
    if (cur->left)
        postfix_dfs(cur->left);
    if (cur->right)
        postfix_dfs(cur->right);
    putchar(cur->val);
}

int cal(int a, int b, char o)
{
    if (o == '+') return a+b;
    if (o == '-') return a-b;
    if (o == '*') return a*b;
    if (o == '/') return a/b;
    cerr << "bad o" << endl;
    return 0;
}

int cal_tree(node_t* cur){
    if (isalpha(cur->val))
        return value[cur->val];
    return cal(cal_tree(cur->left), cal_tree(cur->right), cur->val);
}

int tree_height(node_t *cur)
{
    if (isalpha(cur->val))
        return 1;
    return 1+max(tree_height(cur->left), tree_height(cur->right));
}

void print_tree(node_t *rt)
{
    struct Node{
        node_t *node;
        int pos;
    };

    int tree_h = tree_height(rt);

    vector<Node> *v1 = new vector<Node>(), *v2 = new vector<Node>();
    v1->push_back({rt, (1<<(tree_h-1))-1});
    for (int h = tree_h; h >= 1; --h) {
        int last_pos = 0;
        int bias = 1<<(h-2);

        /* print node value */
        for (Node nd : *v1) {
            for (int i = last_pos; i < nd.pos; ++i)
                putchar(' ');
            putchar(nd.node->val);
            last_pos = nd.pos+1;
            if (h > 1 && !isalpha(nd.node->val)) {
                v2->push_back({nd.node->left, nd.pos - bias});
                v2->push_back({nd.node->right, nd.pos + bias});
            }
        }
        putchar('\n');

        if (h == 1)
            break;

        /* print branch */
        last_pos = 0;
        for (Node nd : *v1) {
            if (isalpha(nd.node->val))
                continue;
            for (int i = last_pos; i < nd.pos-1; ++i)
                putchar(' ');
            printf("/ \\");
            last_pos = nd.pos + 2;
        }
        putchar('\n');

        /* get ready for next loop */
        v1->clear();
        swap(v1, v2);
    }

}

int main()
{
    char in[55];
    cin >> in;

    node_t *rt = build_tree(in);

    postfix_dfs(rt);
    printf("\n");

    print_tree(rt);

    int n; cin >> n;
    for (int i = 0; i < n; ++i) {
        char c; int v;
        cin >> c >> v;
        value[c] = v;
    }
    cout << cal_tree(rt) << endl;

    system("pause");
    return 0;
}

【analysis】

  1. Borrowing the idea of ​​"find the infix expression directly", you can also construct an expression tree directly with infix expressions
  2. The difference is that when directly seeking the infix expression, we put the result of the two numbers on the top of the stack back into the stack. This time we put the new node formed by the two top nodes on the stack.
  3. Because the data size is too large, the array cannot be opened, so dfs cannot be used for recursive printing; instead, bfs printing is used
  4. It is a good way to print the spaces in the middle with the last_pos mark
  5. Hierarchical bfs method: the queue does not use the queue structure but the vector structure, and the depth information is not stored in the node information; using two vector pointers, swap is a convenient way to write at the end of a cycle

Guess you like

Origin blog.csdn.net/w112348/article/details/109406854