转载自:http://www.cnblogs.com/wanghetao/archive/2012/04/23/2466580.html


逆波兰表达式

 

表达式一般由操作数(Operand)、运算符(Operator)组成,例如算术表达式中,通常把运算符放在两个操作数的中间,

这称为中缀表达式(Infix Expression),如A+B。

波兰数学家Jan Lukasiewicz提出了另一种数学表示法,它有两种表示形式:

把运算符写在操作数之前,称为波兰表达式(Polish Expression)或前缀表达式(Prefix Expression),如+AB;

把运算符写在操作数之后,称为逆波兰表达式(Reverse Polish Expression)或后缀表达式(Suffix Expression),如AB+;

其中,逆波兰表达式在编译技术中有着普遍的应用。

 

算法:

一、 将中缀表达式转换成后缀表达式算法:

1、从左至右扫描一中缀表达式。

2、若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数堆栈

3、若读取的是运算符

  (1) 该运算符为左括号"(",则直接存入运算符堆栈。

  (2) 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止。

  (3) 该运算符为非括号运算符:

      (a) 若运算符堆栈栈顶的运算符为括号,则直接存入运算符堆栈。

      (b) 若比运算符堆栈栈顶的运算符优先级高或相等,则直接存入运算符堆栈。

      (c) 若比运算符堆栈栈顶的运算符优先级低,则输出栈顶运算符到操作数堆栈,并将当前运算符压入运算符堆栈。

4、当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。

 

二、逆波兰表达式求值算法:

1、循环扫描语法单元的项目。

2、如果扫描的项目是操作数,则将其压入操作数堆栈,并扫描下一个项目。

3、如果扫描的项目是一个二元运算符,则对栈的顶上两个操作数执行该运算。

4、如果扫描的项目是一个一元运算符,则对栈的最顶上操作数执行该运算。

5、将运算结果重新压入堆栈。

6、重复步骤2-5,堆栈中即为结果值。


c++代码示例

  1. * 

  2. *    这里主要是逆波兰式的实现,使用两个stack 这里用字符串来模拟一个stack,第一步,将中缀表达式转变为后缀表达式 

  3. *    第二步,然后再使用一个stack,计算后缀表达式的结果,这一步很容易出错,考虑到浮点数的问题。 

  4. */  

  5. #include <iostream>  

  6. #include <string>  

  7. #include <stack>  

  8. #include <iomanip>  

  9.   

  10. using namespace std;  

  11.   

  12. int cmp(char ch)     // 运算符优先级   

  13. {  

  14.     switch(ch)  

  15.     {  

  16.         case '+':  

  17.         case '-'return 1;  

  18.         case '*':  

  19.         case '/'return 2;  

  20.         default : return 0;  

  21.     }  

  22. }  

  23. void change(string &s1, string &s2)       // 中缀表达式转变后缀表达式   

  24. {  

  25.     stack <char > s;  

  26.     s.push('#');  

  27.     int i = 0;  

  28.     while(i < s1.length()-1)  

  29.     {  

  30.         if(s1[i] == '(')  

  31.         {  

  32.             s.push(s1[i++]);  

  33.         }  

  34.         else if(s1[i] == ')')  

  35.         {  

  36.             while(s.top() != '(')  

  37.             {  

  38.                 s2 += s.top();  

  39.                 s2 += ' ';  

  40.                 s.pop();  

  41.             }  

  42.             s.pop();  

  43.             i++;  

  44.         }  

  45.         else if(s1[i] == '+'||s1[i] == '-'||s1[i] == '*'||s1[i] == '/')  

  46.         {  

  47.             while(cmp(s.top()) >= cmp(s1[i]))  

  48.             {  

  49.                 s2 += s.top();  

  50.                 s2 += ' ';  

  51.                 s.pop();  

  52.             }  

  53.             s.push(s1[i]);  

  54.             i++;  

  55.         }  

  56.         else  

  57.         {  

  58.             while('0' <= s1[i]&&s1[i] <= '9'||s1[i] == '.')  

  59.             {  

  60.                 s2 += s1[i++];  

  61.             }  

  62.             s2 += ' ';  

  63.         }  

  64.     }  

  65.     while(s.top() != '#')  

  66.     {  

  67.         s2 += s.top();  

  68.         s2 += ' ';  

  69.         s.pop();  

  70.     }  

  71. }  

  72.   

  73. double value(string s2)         // 计算后缀表达式,得到其结果。   

  74. {  

  75.     stack < double> s;  

  76.     double x,y;  

  77.     int i = 0;  

  78.     while(i < s2.length())  

  79.     {  

  80.         if(s2[i] == ' ')  

  81.         {  

  82.             i++;  

  83.             continue;  

  84.         }  

  85.         switch(s2[i])  

  86.         {  

  87.             case '+': x = s.top(); s.pop(); x += s.top(); s.pop(); i++; break;  

  88.             case '-': x = s.top(); s.pop(); x =s.top()-x; s.pop(); i++; break;  

  89.             case '*': x = s.top(); s.pop(); x *= s.top(); s.pop(); i++; break;  

  90.             case '/': x = s.top(); s.pop(); x = s.top()/x; s.pop(); i++; break;  

  91.             default :  

  92.             {  

  93.                 x = 0;  

  94.                 while('0' <= s2[i]&&s2[i] <= '9')  

  95.                 {  

  96.                     x = x*10+s2[i] - '0';  

  97.                     i++;  

  98.                 }  

  99.                 if(s2[i] == '.')  

  100.                 {  

  101.                     double k = 10.0;  

  102.                     y = 0;  

  103.                     i++;  

  104.                     while('0' <= s2[i]&&s2[i] <= '9')  

  105.                     {  

  106.                         y += ((s2[i]-'0')/k);  

  107.                         i++;  

  108.                         k *= 10;  

  109.                     }  

  110.                     x += y;  

  111.                 }  

  112.             }  

  113.         }  

  114.         s.push(x);  

  115.     }  

  116.     return s.top();  

  117. }  

  118. int main(int argc, char const *argv[])  

  119. {  

  120.     int n;  

  121.     string s1,s2;  

  122.     cin>>n;  

  123.     while(n--)  

  124.     {  

  125.         cin>>s1;  

  126.         s2 = "";  

  127.         change(s1,s2);  

  128.         cout<<fixed<<setprecision(2)<<value(s2)<<endl;  

  129.     }  

  130.     return 0;  

  131. }