形如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;
}