栈的应用四则运算表达式求值
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈的应用四则运算表达式求值相关的知识,希望对你有一定的参考价值。
1. 后缀表达式计算结果
(1) 规则
从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶的两个数字出栈,运算结果进栈,一直到最终获得结果。
(2) 示例
后缀表达式:9 3 1 - 3 * + 10 2 / +
- 初始化一个空栈。此栈用来对要运算的数字进出使用;
- 后缀表达式中前三个都是数字,所以9、3、1依次进栈;
- 接下来是"-",所以将栈中的1出栈作为减数,3出栈作为背减数,并运算3-1得到2,再将2进栈;
- 接着是数字3进栈;
- 后面是"*",也就意味着栈中3和2出栈,2与3相乘,得到6,并将6进栈;
- 下面是"+",所以栈中的6和9出栈,9与6相加,得到15,将15进栈;
- 接着是10与2两个数字进栈;
- 接下来是符号"/",因此,栈顶的2与10出栈,10与2相除,得到5,将5进栈;
- 最后一个是"+",所以15与5出栈并相加,得到20,将20进栈;
- 结果是20出栈,栈变为空。
2. 中缀表达式转后缀表达式
(1) 规则
从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
(2) 示例
中缀表达式 "9+(3-1)*3+10/2"
- 初始化一空栈,用来对符号进出栈使用;
- 第一个字符是数字9,输出9,后面是符号"+",进栈;
- 第三个字符是"(",依然是符号,因其只是左括号,还未配对,故进栈;
- 第四个字符是数字3,输出,总表达式为"9 3",接着是"-",进栈;
- 接下来是数字1,输出,总表达式为"9 3 1",后面是符号")",此时,我们需要去匹配此前的"(",所以栈顶依次出栈,并输出,直到"("为止,此时括号上方只有"-",因此输出"-",总的输出表达式为"9 3 1 -";
- 之后是符号"+",此时当前栈顶元素"*"比这个"+"的优先级高,因此栈中元素出栈并输出(没有比"+"更低的优先级,所以全部出栈),总输出表达式为"9 3 1 - 3 * +";然后将当前这个符号"+"进栈;
- 紧接着是数字10,输出,总表达式变为"9 3 1 - 3 * + 10";后面是符号"/",所以"/"进栈;
- 最后一个是数字2,输出,总的表达式为"9 3 1 - 3 * + 10 2";
- 因已经最后,所以将栈中符号全部出栈并输出;最终输出的后缀表达式结果为"9 3 1 - 3 * + 10 2 / +"。
3. 表达式求值
(1) 问题描述
输入一个中缀表达式,如 "1 + 2 - (3-4) *5 + 6/7 ",输出表达式的值。
要求:表达式中可能有多个空格,输出结果为double类型。
(2) 思路
- 先对字符串进行预处理,去掉所有的空格;
- 将中缀表达式软化为后缀表达式;
- 将后缀表达式进行运算得出结果。
(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 }
以上是关于栈的应用四则运算表达式求值的主要内容,如果未能解决你的问题,请参考以下文章