后缀表达式 详解

表达式的表示形式有中缀、前缀和后缀3中形式。中缀表达式按操作符的优先级进行计算(后面代码实现只包括+、-、*、\,小括号),即数学运算。 后缀表达式中只有操作数和操作符。操作符在两个操作数之后。它的计算规则非常简单,严格按照从左到右的次序依次执行每一个操作。每遇到一个操作符,就将前面的两个数执行相应的操作。 

由后缀表达式计算中缀表达式原理:计算机处理后缀表达式求值问题是比较方便的,即将遇到的操作数暂存于一个操作数栈中,凡是遇到操作数,便从栈中pop出两个操作数,并将结果存于操作数栈中,直到对后缀表达式中最后一个操作数处理完,最后压入栈中的数就是后最表达式的计算结果。 

中缀表达式转换为等价的后缀表达式 

中缀表达式不方便与计算机处理,通常要讲中缀表达式转换为一个与之等价的后缀表达式。等价是指两个表达式的计算顺序和计算结果完全相同。 

中缀表达式:0.3/(5*2+1)# 

的等价后缀表达式是:0.3 5 2 * 1 + /# 

仔细观察这两个等价的表达式可知,操作数的出现次序是相同的,但运算符的出现次序是不同的。在后缀表达式中,运算符的出现次序是实际进行操作的次序;在中追表达式中,由于受到操作符的优先级和括号的影响,操作符出现次序与实际进行操作的次序很可能是不一样的。 

算法描述: 

将中缀表达式转换为等价的后缀表达式的过程要使用一个栈放“(”,具体可以按照下面的方式进行。 

(1)从左到右依次扫描中缀表达式的每一个字符,如果是数字字符和圆点“.”则直接将它们写入后缀表达式中。 

(2)如果遇到的是开括号“(”,则将它们压入一个操作符栈(不需要与栈顶操作符相比较),它表明一个新的计算层次的开始,在遇到和它匹配的闭括号“)”时,将栈中的元素弹出来并放入后缀表达式中,直到栈顶元素为“(”时,将栈顶元素“(”弹出(不需要加入后缀表达式),表明这一层括号内的操作处理完毕。 

(3)如果遇到的是操作符,则将该操作符和操作符栈顶元素比较: 

    1、当所遇到的操作符的优先级小于或等于栈顶元素的优先级时,则取 出栈顶元素放入后缀表达式,并弹出该栈顶元素,反复执行直到当前操作符的优先级大于栈顶元素的优先级小于;

     2、当所遇到的操作符的优先级大于栈顶元素的优先级的时则将它压入栈中。 


(4)重复上述步骤直到遇到中缀表达式的结束符标记“#”,弹出栈中的所有元素并放入后缀表达式中,转换结束


代码如下:

[cpp]  view plain copy
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. #include<string>  
  5. #include<vector>  
  6. #include<stack>  
  7. #include<algorithm>  
  8. using namespace std;  
  9.   
  10. int pre(char a) //操作符优先级比较  
  11. {  
  12.     if(a == '=' || a == '(')  
  13.         return 0;  
  14.     else if(a == '+' || a == '-')  
  15.         return 1;  
  16.     else if(a == '*' || a == '/')  
  17.         return 2;  
  18. }  
  19.   
  20. int main()  
  21. {  
  22.     int ncase, len;  
  23.     string str;  
  24.     char tmp;  
  25.     stack<char> ope; //操作符  
  26.     vector<char> ans;//后缀表达式  
  27.     vector<char>::iterator start, end;  
  28.     scanf("%d", &ncase);  
  29.     getchar(); //清除输入垃圾  
  30.     while(ncase--)  
  31.     {  
  32.         while(!ope.empty()) //初始化  
  33.             ope.pop();  
  34.         ans.clear();  
  35.         ope.push('='); //结束标志  
  36.         cin>>str;  
  37.         len = str.length();  
  38.         for(int i = 0 ; i < len; ++i)  
  39.         {  
  40.             if(str[i] >= '0' && str[i] <= '9'//操作数直接存入ans  
  41.                 ans.push_back(str[i]);  
  42.             else if(str[i] == '('//左括号入栈  
  43.                 ope.push(str[i]);  
  44.             else if(str[i] == ')'//右括号,将匹配的左括号内容存入ans,左括号出栈  
  45.             {  
  46.                 while (ope.top() != '(')  
  47.                 {  
  48.                     ans.push_back(ope.top());  
  49.                     ope.pop();  
  50.                 }  
  51.                 ope.pop(); //左括号出栈  
  52.             }  
  53.             else if(pre(str[i]) > pre(ope.top())) //优先级大于栈顶元素则入栈  
  54.                 ope.push(str[i]);  
  55.             else //小于栈顶元素  
  56.             {  
  57.                 while(pre(str[i]) <= pre(ope.top()))  
  58.                 {  
  59.                     ans.push_back(ope.top());  
  60.                     ope.pop();  
  61.                 }  
  62.                 ope.push(str[i]);  
  63.             }         
  64.         }  
  65.         while(ope.top() != '='//其余操作符存入后缀表达式中  
  66.         {  
  67.             ans.push_back(ope.top());  
  68.             ope.pop();  
  69.         }  
  70.         for(start = ans.begin(), end = ans.end(); start < end; ++start)  
  71.             printf("%c", *start);  
  72.         printf("\n");  
  73.     }  
  74.     return 0;  
  75. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值