表达式求值——栈的应用

 

转载请注明出处:http://www.cnblogs.com/luna-lovegood/archive/2012/07/17/2596501.html

 一个算术表达式,含有数字(为简化处理,数字只有一位),运算符:+-*,以及括号,求表达式的值。

 给出的表达式是一般我们见到的中缀表达式,即运算符位于操作数之间。如果把中缀表达式转化为后缀表达式,那么对后缀表达式求值将会很方便。

 后缀表达式特点

  1.操作符位于操作数之后;

  2.没有括号;

  3.运算符没有优先级。

 中缀表达式转化为后缀表达式的步骤:(还有一种方法:写成二叉树的形式,进行后序遍历为后缀表达式,中序表达式为中缀表达式)

  1.初始化一个空操作符栈和空结果字符串;

  2.从前到后读取中缀表达式的字符,如果是操作数,加到结果字符串后面;

  3.如果是操作符,分两种情况入栈:

    a.如果待入栈操作符优先级大于栈顶操作符,直接入栈;

    b.如果待入栈操作符优先级小于或等于栈顶操作符,栈顶操作符加到结果字符串后面;重复b过程直到遇到前括号‘(’或栈顶操作符优先级比待入栈操作符小,待入栈操作符入栈。

  4.如果是前括号‘(’,直接入栈;

  5.如果是后括号,将栈中操作符依次弹出,直至遇到一个前括号‘(’结束。前括号出栈。

  最后结果字符串就是后缀表达式。

  后缀表达式求值的步骤

  1.初始化一个空操作数栈;

  2.从前到后读取后缀表达式字符。如果是操作数直接入栈。如果读到一个操作符@,弹出栈顶元素a和新的栈顶元素b,执行b @ a,将结果压入栈中;

  3.最后栈中只剩下一个元素,即表达式的值。

 

  关于中缀表达式转换成后缀表达式与后缀表达式正确性的说明

  先观察一些例子:

  1.假设中缀表达式没有括号,且所有运算符优先级相同。比如a+b-c+d-e+f ,将被转化为ab+c-d+e-f+。此时用括号来说明后缀表达式执行顺序:((((( ab+ ) c- ) d+ ) d- ) f+ ),运算顺序没有改变。

  2.假设中缀表达式没有括号,但是运算符优先级不同。比如a+b*c+d-e*f,将被转化为 abc*+d+ef*-,用括号来说明后缀表达式执行顺序:((( a ( bc* ) + ) d+ ) ( ef* ) - ),运算顺序依然没有变。

  3.假设中缀表达式有括号。比如(a+b)*(c+d)*e+f,将被转化为ab+cd+*e*f+,用括号表示执行顺序(((( ab+ ) ( cd+ ) * ) e* ) f+ )。运算顺序还是没有改变。

 

  不难观察出以下5点

  1.后缀表达式中操作数出现的顺序和中缀表达式一样。这是因为操作数是直接加入结果字符串;

  2.每个操作符都会入栈一次,出栈一次;

  3.在没有括号时,如果相邻两个操作符优先级相同或前一个操作符的优先级高,则后缀表达式中操作符出现的顺序和中缀表达式一样。因为后一个操作符入栈时,栈顶元素一定是前一个相邻的操作符,如果其优先级小于等于待入栈的,则前一个操作符被弹出并加入结果字符串,后缀表达式中操作符顺序得到保持。

  4.在没有括号时,如果相邻两个操作符,后者优先级大与前者,后者将直接被压入栈中,且位于前者之上。在出栈时,后者将先出栈,因而后缀表达式中,操作符顺序发生交换,即中缀表达式中要先运算的操作在后缀表达式中出现在前面。

  5.出现括号。括号中的处理因为遵循前4点,不再赘述,而括号的内容作为一个整体的性质得到维护。

  参考文章:

  http://blog.csdn.net/daheiantian/article/details/6553713

  http://blog.csdn.net/niushuai666/article/details/6702964

  http://www.cnblogs.com/luna-lovegood/archive/2012/07/17/2596464.html

代码:

复制代码
 1 //zzy2012.7.17
 2 //利用后缀表达式对算数表达式求值
 3 //不含符号变量处理,且数字都是一位,运算符仅含+、-、*和括号
 4 #include<cstdio>
 5 #include<iostream>
 6 #include<cstring>
 7 #define NUM 200
 8 
 9 using namespace std;
10 
11 char s[NUM],a[NUM],stack[NUM];
12 int stacknum[NUM];
13 
14 int trans(char s[NUM],char a[NUM],char stack[NUM],int lens){
15     int lena = 0,top = 0;
16     for(int i=0; i<lens; i++){
17         if(s[i]>='0' && s[i]<='9'){
18             a[lena++] = s[i];
19         }
20         else if(s[i]=='+' || s[i]=='-'){
21             while(top>0 && stack[top-1]!='(')
22                 a[lena++] = stack[--top];
23             stack[top++] = s[i];
24         }
25         else if(s[i] == '*'){
26             while(top>0 && stack[top-1]!='(' && stack[top-1]!='+' && stack[top-1]!='-')
27                 a[lena++] = stack[--top];
28             stack[top++] = s[i];
29         }
30         else if(s[i]=='(')
31             stack[top++] = s[i];
32         else if(s[i]==')'){
33             while(top>0 && stack[top-1]!='(')
34                   a[lena++] = stack[--top];
35             top--;
36         }
37     }
38     while(top>0){
39         a[lena++] = stack[--top];
40     }
41     return lena;
42 }
43 
44 int calcu(char a[NUM],int stack[NUM],int lena){
45     int top=0;
46     for(int i=0; i<lena; i++)
47         if(a[i]>='0' && a[i]<='9')
48             stack[top++] = a[i]-'0';
49         else{
50             if(a[i]=='+')
51                 stack[top-2] = stack[top-2] + stack[top-1];
52             else if(a[i] == '-')
53                 stack[top-2] = stack[top-2] - stack[top-1];
54             else if(a[i]=='*')
55                 stack[top-2] = stack[top-2] * stack[top-1];
56             top--;
57         }
58     return stack[0];
59 }
60 
61 int main()
62 {
63     int ans,lens,lena;
64     gets(s);
65     lens = strlen(s);
66     lena = trans(s,a,stack,lens);//将中缀表达式转换横后缀表达式,返回值是后缀表达式a的长度
67     ans = calcu(a,stacknum,lena);//计算后缀表达式值
68     printf("%d\n",ans);
69     return 0;
70 }
复制代码
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章