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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈的应用四则运算表达式求值相关的知识,希望对你有一定的参考价值。

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

 

以上是关于栈的应用四则运算表达式求值的主要内容,如果未能解决你的问题,请参考以下文章

栈的应用—算术表达式求值

栈的典型应用-表达式求值

数据结构之栈的应用:中缀表达式求值

中缀表达式转换成后缀表达式并求值

表达式求值

[UPC] Postfix Evaluation 后缀表达式求值 | 栈的简单应用