表达式树 csu1655 文本计算器

传送门:点击打开链接

题意:计算表达式,其中里面含有加减乘除括号


如果里面没有括号,那么使用栈简单维护一下即可

但是如果里面有括号了,或者有更复杂的运算符号,那么推荐使用表达式树来做

其实表达式树构造起来并没有想象中的那么麻烦,构造好之后直接分治算出答案即可

表达式树的核心思维就是找同优先级的最后一个运算符的位置,然后按照优先级递减顺序去考虑即可

#include<map>
#include<set>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
using namespace std;
typedef long long LL;
typedef pair<int, int>PII;
 
const int MX = 1e5 + 5;
 
char op[MX];
int lch[MX], rch[MX], s[MX], r;
 
int build(char *S, int L, int R) {
    int c[] = { -1, -1}, p = 0, u;
 
    int sum = 0, sign = true;
    for(int i = L; i <= R; i++) {
        if(isdigit(S[i])) sum = sum * 10 + S[i] - '0';
        else {
            sign = false;
            break;
        }
    }
 
    if(sign) {
        u = ++r;
        op[u] = '.';
        s[u] = sum;
        return u;
    }
 
    for(int i = L; i <= R; i++) {
        switch(S[i]) {
        case '(': p++; break;
        case ')': p--; break;
        case '+': case '-': if(!p) c[0] = i; break;
        case '*': case '/': if(!p) c[1] = i; break;
        }
    }
 
    if(c[0] < 0) c[0] = c[1];
    if(c[0] < 0) u = build(S, L + 1, R - 1);
    else {
        u = ++r;
        op[u] = S[c[0]];
        lch[u] = build(S, L, c[0] - 1);
        rch[u] = build(S, c[0] + 1, R);
    }
    return u;
}
 
double solve(int u) {
    if(op[u] == '.') return s[u];
    double al = solve(lch[u]), ar = solve(rch[u]);
    switch(op[u]) {
    case '+': return al + ar;
    case '-': return al - ar;
    case '*': return al * ar;
    case '/': return al / ar;
    }
}
 
char S[MX];
int main() {//FIN;
    while(gets(S)) {
        r = 0;
        int len = strlen(S);
        int rt = build(S, 0, len - 1);
        printf("%.4lf\n", solve(rt));
    }
    return 0;
}


你可能感兴趣的:(表达式树 csu1655 文本计算器)