表达式树(图论) By ACReaper
形如6*(2+3)+9计算其值,要是在面向对象的语言中,用脱窗口的方法是很好解决的,是不。不过我们要写的是算法。
思想:
通过观察表达式我们可以发现一个规律,就是我们可以先找到最后运算的符号,然后计算其左边,其右边,接着把它连接如符号计算。这个思想和简单,也很容易理解,其实这个思想所建立的树也就是后缀树。
代码实现如下:
#include <stdio.h> #include <string.h> const int maxn = 1000; int lch[maxn], rch[maxn]; char op[maxn]; char input[maxn]; int nc = 0; int build_tree(char *s,int x,int y){ int i,c1 = -1,c2 = -1,p =0;//p用来标记是否在括号内 int u; if(y - x == 0){//当只有一个字符,也就是叶子结点,则,生成叶子结点,存入 u = ++nc; lch[u] = rch[u] = 0; op[u] = s[x]; return u; } for(i = x; i <= y; i++){ switch(s[i]){ case '(':p++;break;//进入括号内加加 case ')':p--;break;//出括号渐减 case '+':case '-':if(!p) c1 = i;break; case '*':case '/':if(!p) c2 = i;break; } } if(c1 < 0) c1 = c2; if(c1 < 0) return build_tree(s,x + 1,y - 1); u = ++nc; lch[u] = build_tree(s,x,c1 - 1); rch[u] = build_tree(s,c1 + 1,y); op[u] = s[c1]; return u; } int count_value(int root){ if(lch[root] == rch[root] && lch[root] == 0){ return op[root] - '0'; }else{ switch(op[root]){ case '+':return count_value(lch[root]) + count_value(rch[root]); case '-':return count_value(lch[root]) - count_value(rch[root]); case '*':return count_value(lch[root]) * count_value(rch[root]); case '/':return count_value(lch[root]) / count_value(rch[root]); } } } int main(){ while(scanf("%s",input) != EOF){ memset(lch,0,sizeof(lch)); memset(rch,0,sizeof(rch)); int len = strlen(input); int root = build_tree(input,0,len - 1); printf("%d\n",count_value(root)); } return 0; }