中缀转后缀(逆波兰式)示例1
依然是需要1个栈结构(符号栈)(存放运算符的)
我们从头开始遍历。
遇见小括号(了,因为栈是空的,左括号(入栈
然后遇见1,中缀转后缀,碰见数字,直接输出。
然后遇见+号,针对于栈里的左括号(,优先级是高还是低?
只要栈顶是左括号(,就有一个优先级比较高的式子出现了,所以+比左括号(的优先级要大,也就是说,现在遇到的任意符号都比栈顶的左括号(优先级要大,所以这个+号直接入栈,
然后遇见2,遇见数字,直接输出
然后遇见右括号)
有右括号,那么之前就一定有左括号了,我们就要从右括号)开始,一直运算,直到碰见左括号(为止
因为小括号括起来的优先级是最大的
一直算到把左括号(出栈
接着遇到 *,栈是空的,直接把 * 入栈
然后遇到左括号(,左括号(入栈
左括号是优先级比较高的表达式的开始。
只要遇到左括号,就不用比较优先级了,直接入栈
然后遇见3,直接输出
然后遇见+,这个+要和栈顶元素比较,一看这个栈顶元素是(,遇见左括号(都是直接入栈。
然后碰见4,直接输出
然后碰见右括号),开始计算这个小括号的内容了,然后右括号)就不用入栈了,+直接出栈,然后左括号(出栈,
如果遍历遇到右括号,就直接出栈,直到左括号(出栈。
相当于是把一个小括号的表达式处理完了。
最后符号栈剩下的按原样输出
中缀转后缀(逆波兰式)示例2
我们从头开始遍历。遇见数字2,直接输出。
然后遇见符号+,现在栈是空的,就直接入栈。
然后遇见左括号(,左括号直接入栈,因为左括号(是优先级更高的表达式的开。
然后遇见4,直接输出
然后遇见符号+,此时栈顶元素是左括号(,任何符号和左括号比,都是认为优先级高,直接入栈就好啦,
然后遇见6,直接输出
然后遇见右括号),就不用入栈了,就是现在是优先级最高的表达式,就直接一直出栈,计算,直到到左括号(输出出来就结束,
然后遇见除法/,此时栈顶元素是+,/的优先级高,直接入栈。
然后遇见数字2,直接输出
然后遇见符号+,此时栈顶元素是/,+的优先级比/低啊,所以先计算除法/,把除法/出栈,
然后继续比较,现在是符号+和栈顶元素+比较,优先级一样,按顺序从左向右算,栈里的+出现的比较早,所以也是出栈,先计算。
现在栈空了,没得比较了,把6前面的符号+入栈,
然后遇见数字6,直接输出
然后遇见除法/,优先级高于此时的栈顶元素+,/直接入栈,
然后遇见数字3,直接输出
然后把栈里的符号依次输出就完了。
我们验证一下中缀
最后结果是2+5+2=9
我们验证一下后缀
后缀表达式在求解的时候,把数字入栈
然后遇见符号+
出栈2个元素进行+号运算,得出结果10,入栈
然后遇见数字2,就入栈
然后遇见除法/,
出栈2个元素,先出栈的作右操作数,后出栈的作左操作数
2和10出栈,10/2=5,5入栈
然后遇见+号,出栈2个元素,2和5,2+5=7,7入栈
然后遇见数字6,入栈,然后遇见数字3,入栈
然后遇见除法/,出栈3和6两个元素,6/3=2,2入栈
最后遇见符号+,出栈2个元素,7+2=9,最后的结果:9
中缀转后缀总结
代码实现
#include <iostream>
#include <string>
#include <stack>
using namespace std;
//比较符号优先级的函数
bool Priority(char ch, char topch)
{
if ((ch == '*' || ch == '/') && (topch == '+' || topch == '-'))
return true;
if (topch == '(' && ch != ')')
return true;
return false;
}
//中缀表达式 => 后缀表达式
string MiddleToEndExpr(string expr)
{
string result;//定义结果
stack<char> s;//存储的是符号
for (char ch : expr)//遍历字符串
{
if (ch >= '0' && ch <= '9')//如果遇见数字,直接输出
{
result.push_back(ch);//输出的结果放在result里面
}
else//如果遇见的是符号
{
for (;;)
{
//处理符号了
if (s.empty() || ch == '(')//如果当前栈是空的,或者当前符号是(,直接入栈
{
s.push(ch);
break;
}
//比较当前符号ch和栈顶符号top的优先级
char topch = s.top();//获取栈顶符号
//Priority:true:ch > topch false:ch <= topch
if (Priority(ch, topch))//ch > topch
{
s.push(ch);//入栈
break;//结束,进行遍历字符串的下一个字符
}
else//ch <= topch
{
s.pop();//出栈
if (topch == '(')//如果遇见),是要一直出栈的,直到遇见(为主
break;//左右括号不用入到result里面
result.push_back(topch);//输出
}
}
}
}
//如果符号栈还存留符号,直接输出到后缀表达式里面 + /
while (!s.empty())
{
result.push_back(s.top());
s.pop();
}
return result;
}
int main()
{
cout << MiddleToEndExpr("(1+2)*(3+4)") << endl;
cout << MiddleToEndExpr("2+(4+6)/2+6/3") << endl;
cout << MiddleToEndExpr("2+6/(4-2)+(4+6)/2") << endl;
}