天天看点

中缀表达式转换为后缀表达式求值算法

转载自: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. *    这里主要是逆波兰式的实现,使用两个stack 这里用字符串来模拟一个stack,第一步,将中缀表达式转变为后缀表达式 
  2. *    第二步,然后再使用一个stack,计算后缀表达式的结果,这一步很容易出错,考虑到浮点数的问题。 
  3. */  
  4. #include <iostream>  
  5. #include <string>  
  6. #include <stack>  
  7. #include <iomanip>  
  8. using namespace std;  
  9. int cmp(char ch)     // 运算符优先级   
  10. {  
  11.     switch(ch)  
  12.     {  
  13.         case '+':  
  14.         case '-': return 1;  
  15.         case '*':  
  16.         case '/': return 2;  
  17.         default : return 0;  
  18.     }  
  19. }  
  20. void change(string &s1, string &s2)       // 中缀表达式转变后缀表达式   
  21.     stack <char > s;  
  22.     s.push('#');  
  23.     int i = 0;  
  24.     while(i < s1.length()-1)  
  25.         if(s1[i] == '(')  
  26.         {  
  27.             s.push(s1[i++]);  
  28.         }  
  29.         else if(s1[i] == ')')  
  30.             while(s.top() != '(')  
  31.             {  
  32.                 s2 += s.top();  
  33.                 s2 += ' ';  
  34.                 s.pop();  
  35.             }  
  36.             s.pop();  
  37.             i++;  
  38.         else if(s1[i] == '+'||s1[i] == '-'||s1[i] == '*'||s1[i] == '/')  
  39.             while(cmp(s.top()) >= cmp(s1[i]))  
  40.             s.push(s1[i]);  
  41.         else  
  42.             while('0' <= s1[i]&&s1[i] <= '9'||s1[i] == '.')  
  43.                 s2 += s1[i++];  
  44.             s2 += ' ';  
  45.     while(s.top() != '#')  
  46.         s2 += s.top();  
  47.         s2 += ' ';  
  48.         s.pop();  
  49. double value(string s2)         // 计算后缀表达式,得到其结果。   
  50.     stack < double> s;  
  51.     double x,y;  
  52.     while(i < s2.length())  
  53.         if(s2[i] == ' ')  
  54.             continue;  
  55.         switch(s2[i])  
  56.             case '+': x = s.top(); s.pop(); x += s.top(); s.pop(); i++; break;  
  57.             case '-': x = s.top(); s.pop(); x =s.top()-x; s.pop(); i++; break;  
  58.             case '*': x = s.top(); s.pop(); x *= s.top(); s.pop(); i++; break;  
  59.             case '/': x = s.top(); s.pop(); x = s.top()/x; s.pop(); i++; break;  
  60.             default :  
  61.                 x = 0;  
  62.                 while('0' <= s2[i]&&s2[i] <= '9')  
  63.                 {  
  64.                     x = x*10+s2[i] - '0';  
  65.                     i++;  
  66.                 }  
  67.                 if(s2[i] == '.')  
  68.                     double k = 10.0;  
  69.                     y = 0;  
  70.                     while('0' <= s2[i]&&s2[i] <= '9')  
  71.                     {  
  72.                         y += ((s2[i]-'0')/k);  
  73.                         i++;  
  74.                         k *= 10;  
  75.                     }  
  76.                     x += y;  
  77.         s.push(x);  
  78.     return s.top();  
  79. int main(int argc, char const *argv[])  
  80.     int n;  
  81.     string s1,s2;  
  82.     cin>>n;  
  83.     while(n--)  
  84.         cin>>s1;  
  85.         s2 = "";  
  86.         change(s1,s2);  
  87.         cout<<fixed<<setprecision(2)<<value(s2)<<endl;  
  88.     return 0;  
  89. }