1、简介
在数据结构中,有一种数据结构叫做:Stack,LIFO(Last In First Out),在这个结构中,有个后缀表达式计算,运用该数据结构进行计算。
栈是一种只允许一端操作的线性数据结构,具有LIFO(last in first out)的特点,具有广泛的应用,如我在游戏编程模式--命令模式(2)中使用栈的结构来实验撤销、重做功能。现在打算用栈结构来实现后缀表达式的计算。
后缀表达式也叫逆波兰表达式,其求值过程可以用到栈来辅助存储。
2、后缀表达式
后缀表达式,指的是不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则)。
例如 5+(2+3)*4 转换为后缀表达式为 523+4*+
3、后缀表达式的计算
规则:从左向右扫描,遇到数字压栈,遇到操作符,弹出栈顶的两个元素,先弹出的元素在右边,后弹出来的在左边,进行计算后,将结果压栈,再往后扫描,直到扫描结束,输出栈顶元素,即为最终结果。
以 523+4*+为例
5压栈 2压栈 3压栈 遇到+号,弹出3 2,计算2+3,将5压栈,此时栈为5 5,将4压栈,遇到*号,弹出4 5,计算5*4,将20压栈 此时栈为5 20 ,遇到+号,计算5+20,将25压栈,扫描结束,输出25。
以上就是计算过程。下面用C++编写代码,为了方便标记算式的结束,在末尾我们加上#,用来标识算式结束,这里我们只进行四则运算
#include <iostream>
#include <stack>
#include "string"
using namespace std;
int main()
{
stack<int> a;
string temp;
cin >> temp;
int i = 0;
while (true)
{
if (temp[i]=='#') cout << a.top(); break;
if (temp[i]<='9'&&temp[i]>='0') a.push(temp[i]-48);
else
{
int x, y;
y = a.top(); a.pop();
x = a.top(); a.pop();
switch (temp[i])
{
case '+':a.push(x + y); break;
case '-':a.push(x - y); break;
case '*':a.push(x * y); break;
case '/':a.push(x / y); break;
default:break;
}
}
++i;
}
cin >> temp;
return 0;
}
4、中缀表达式转后缀表达式
4.1、规则
中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。
转换过程需要用到栈,具体过程如下:
1)如果遇到操作数,我们就直接将其输出。
2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。
3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。
4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) "的情况下我们才弹出" ( ",其他情况我们都不会弹出" ( "。
5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。
4.2、实例
规则很多,还是用实例比较容易说清楚整个过程。以上面的转换为例,输入为a + b * c + (d * e + f)*g,处理过程如下:
1)首先读到a,直接输出。
2)读到“+”,将其放入到栈中。
3)读到b,直接输出。
4)读到“*”,因为栈顶元素"+"优先级比" * " 低,所以将" * "直接压入栈中。
5)读到c,直接输出
6)读到" + ",因为栈顶元素" * "的优先级比它高,所以弹出" * "并输出, 同理,栈中下一个元素" + "优先级与读到的操作符" + "一样,所以也要弹出并输出。然后再将读到的" + "压入栈中。
7)下一个读到的为"(",它优先级最高,所以直接放入到栈中。
8)读到d,将其直接输出。
9)读到" * ",由于只有遇到" ) "的时候左括号"("才会弹出,所以" * "直接压入栈中。
10)读到e,直接输出。
11)读到" + ",弹出" * "并输出,然后将"+"压入栈中。
12)读到f,直接输出。
13)接下来读到“)”,则直接将栈中元素弹出并输出直到遇到"("为止。这里右括号前只有一个操作符"+"被弹出并输出。
14)读到" * ",压入栈中。读到g,直接输出。
15)此时输入数据已经读到末尾,栈中还有两个操作符“*”和" + ",直接弹出并输出。至此整个转换过程完成。程序实现代码后续再补充了。
4.3、转换的另一种方法
1)先按照运算符的优先级对中缀表达式加括号,变成( ( a+(b*c) ) + ( ((d*e)+f) *g ) )
2)将运算符移到括号的后面,变成((a(bc)*)+(((de)*f)+g)*)+
3)去掉括号,得到abc*+de*f+g*+
具体细节关注微信公众号 【阿龙学堂】