码迷,mamicode.com
首页 > 其他好文 > 详细

【栈的应用】四则运算表达式求值

时间:2016-06-15 01:37:01      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:

1. 后缀表达式计算结果

(1) 规则

  从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶的两个数字出栈,运算结果进栈,一直到最终获得结果。

(2) 示例

  后缀表达式:9 3 1 - 3 * + 10 2 / +

  1. 初始化一个空栈。此栈用来对要运算的数字进出使用;
  2. 后缀表达式中前三个都是数字,所以9、3、1依次进栈;
  3. 接下来是"-",所以将栈中的1出栈作为减数,3出栈作为背减数,并运算3-1得到2,再将2进栈;
  4. 接着是数字3进栈;
  5. 后面是"*",也就意味着栈中3和2出栈,2与3相乘,得到6,并将6进栈;
  6. 下面是"+",所以栈中的6和9出栈,9与6相加,得到15,将15进栈;
  7. 接着是10与2两个数字进栈;
  8. 接下来是符号"/",因此,栈顶的2与10出栈,10与2相除,得到5,将5进栈;
  9. 最后一个是"+",所以15与5出栈并相加,得到20,将20进栈;
  10. 结果是20出栈,栈变为空。

2. 中缀表达式转后缀表达式

(1) 规则

  从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。

(2) 示例

  中缀表达式 "9+(3-1)*3+10/2"

  1. 初始化一空栈,用来对符号进出栈使用;
  2. 第一个字符是数字9,输出9,后面是符号"+",进栈;
  3. 第三个字符是"(",依然是符号,因其只是左括号,还未配对,故进栈;
  4. 第四个字符是数字3,输出,总表达式为"9 3",接着是"-",进栈;
  5. 接下来是数字1,输出,总表达式为"9 3 1",后面是符号")",此时,我们需要去匹配此前的"(",所以栈顶依次出栈,并输出,直到"("为止,此时括号上方只有"-",因此输出"-",总的输出表达式为"9 3 1 -";
  6. 之后是符号"+",此时当前栈顶元素"*"比这个"+"的优先级高,因此栈中元素出栈并输出(没有比"+"更低的优先级,所以全部出栈),总输出表达式为"9 3 1 - 3 * +";然后将当前这个符号"+"进栈;
  7. 紧接着是数字10,输出,总表达式变为"9 3 1 - 3 * + 10";后面是符号"/",所以"/"进栈;
  8. 最后一个是数字2,输出,总的表达式为"9 3 1 - 3 * + 10 2";
  9. 因已经最后,所以将栈中符号全部出栈并输出;最终输出的后缀表达式结果为"9 3 1 - 3 * + 10 2 / +"。

3. 表达式求值

(1) 问题描述

  输入一个中缀表达式,如 "1 + 2 - (3-4)   *5 + 6/7    ",输出表达式的值。

  要求:表达式中可能有多个空格,输出结果为double类型。

(2) 思路

  1. 先对字符串进行预处理,去掉所有的空格;
  2. 将中缀表达式软化为后缀表达式;
  3. 将后缀表达式进行运算得出结果。

(3) 参考代码

技术分享
  1 #include <iostream>
  2 #include <stack>
  3 #include <string>
  4 using namespace std; 
  5 
  6 int cmp(char op) // 运算符优先级
  7 {
  8     switch (op)
  9     {
 10         case ‘+‘:
 11         case ‘-‘: return 1; 
 12         case ‘*‘:
 13         case ‘/‘: return 2; 
 14         default : return 0; 
 15     }
 16 }
 17 
 18 void trim(char *src)
 19 {
 20     char * fp = src;  
 21     while (*src) 
 22     {  
 23         if (*src != ‘ ‘)  // 如果不是空格就复制  
 24         {
 25             *fp = *src;  
 26             fp++;  
 27         }  
 28         src++;  
 29     }  
 30     *fp = ‘\0‘ ; //封闭字符串 
 31 }
 32 
 33 void trim(string &str)
 34 {
 35     // 因为str.c_str() 是const的,不能直接修改,所以要复制一个临时的,然后修改后换回去  
 36     char tmp[str.size()+1];  
 37     memcpy(&tmp, str.c_str(), str.size() + 1);  
 38     trim(tmp);    // 重载trim,调用C风格的函数  
 39     str = tmp;  
 40 }
 41 
 42 string change(string str) // 中缀表达式转化为后缀
 43 {
 44     string ret; 
 45     stack<char> op; 
 46     op.push(‘#‘); 
 47     int len = str.length(), i = 0; 
 48     while (i < len)
 49     {
 50         if (str[i] == ‘(‘) op.push(str[i++]); 
 51         else if (str[i] == ‘)‘)
 52         {
 53             while (op.top() != ‘(‘)
 54             {
 55                 ret += op.top(); 
 56                 ret += ‘ ‘; 
 57                 op.pop(); 
 58             }
 59             op.pop(); 
 60             i++; 
 61         }
 62         else if (str[i] == ‘+‘ || str[i] == ‘-‘ || str[i] == ‘*‘ || str[i] == ‘/‘)
 63         {
 64             while (cmp(op.top()) >= cmp(str[i]))
 65             {
 66                 ret += op.top(); 
 67                 ret += ‘ ‘; 
 68                 op.pop(); 
 69             }
 70             op.push(str[i]);
 71             i++; 
 72         }
 73         else 
 74         {
 75             while (str[i] >= ‘0‘ && str[i] <= ‘9‘ || str[i] == ‘.‘)
 76             {
 77                 ret += str[i++]; 
 78             }
 79             ret += ‘ ‘; 
 80         }
 81     }
 82     while (op.top() != ‘#‘)
 83     {
 84         ret += op.top(); 
 85         ret += ‘ ‘; 
 86         op.pop(); 
 87     }
 88     return ret; 
 89 }
 90 
 91 double value(string str) // 后缀表达式求值
 92 {
 93     stack<double> s; 
 94     double x, y; 
 95     int i = 0; 
 96     while (i < str.length())
 97     {
 98         if (str[i] == ‘ ‘)
 99         {
100             i++; 
101             continue; 
102         }
103         switch(str[i])
104         {
105             case ‘+‘:
106                 x = s.top(); s.pop(); x = s.top() + x; s.pop(); 
107                 i++; break;
108             case ‘-‘:
109                 x = s.top(); s.pop(); x = s.top() - x; s.pop(); 
110                 i++; break;
111             case ‘*‘:
112                 x = s.top(); s.pop(); x = s.top() * x; s.pop(); 
113                 i++; break;
114             case ‘/‘:
115                 x = s.top(); s.pop(); x = s.top() / x; s.pop(); 
116                 i++; break;
117             default : 
118             {
119                 x = 0; 
120                 while (str[i] >= ‘0‘ && str[i] <= ‘9‘)
121                 {
122                     x = x * 10 + str[i] - ‘0‘; 
123                     i++; 
124                 }
125                 if (str[i] == ‘.‘)
126                 {
127                     double k = 10.0; 
128                     y = 0;
129                     i++; 
130                     while (str[i] >= ‘0‘ && str[i] <= ‘9‘)
131                     {
132                         y += ((str[i] - ‘0‘) / k); 
133                         i++; 
134                         k *= 10; 
135                     }
136                     x += y; 
137                 }
138             }
139         }
140         cout << x << endl;
141         s.push(x); 
142     }
143     return s.top(); 
144 }
145 
146 
147 int main(int argc, char *argv[])
148 {
149     string expression;
150     while (getline(cin, expression))
151     {
152         trim(expression); 
153         expression = change(expression); 
154         cout << expression << endl; 
155         cout << value(expression) << endl;
156     }
157     return 0; 
158 }
View Code

 

【栈的应用】四则运算表达式求值

标签:

原文地址:http://www.cnblogs.com/xiaoxxmu/p/5585905.html

踩
(0)
赞
(0)
   
举报
评论 一句话评论(0)
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!