前两天收到了一个作业题,讲的是把中序表达式表示成逆向波兰表达式,但是没理解,按照网上的方法做了下,搞了半天,发现总差一点,检查了一下代码,发现是在比较操作符优先级时出错了
下面对它的完整考虑方法
读入的括号必须是英文状态下的!
其算法的完整思路应该是:
- 当轮到的a[i]的是数子时,直接输出出来;
- 当读取的是运算符时,不直接输出,先入栈存储(存储是针对栈中无其他运算符),然后进行优先级的比较:
1)如果该运算符的优先级比栈顶元素(即运算符或者左括号,这个之后再说)的要高,那么就入栈;
2)如果该运算符的优先级没有栈顶的高,那么栈顶的操作符就输出来并出栈,再接着拿当前栈顶操作符的优先级与待入栈的元素a[i]进行比较,以此类推;直到,,,,(第三步)
3.如果读取到的运算符为“(”,那么就直接入栈存储;
4.如果读取到的运算符为“)”,那么直接输出栈中元素,并从栈中弹出运算符,直到遇到“(”,“(”和“)”不用输出;
5.当字符串全部读取过一遍后,将栈中的运算符按序全部输出再弹出(除了“(”),直到!s.empty()的值为假
在写主要代码之前,我们先看一下定义运算符优先级的代码:
int priority(char ch)
{
if (ch == '*' || ch == '/')
return 1;
if (ch == '+' || ch == '-')
return 0;
if (ch == '(')
return -1;
else
return -2;//这是作为意外情况发生时进行判定的手段,万一没载入我想要的呢
}
这个优先级函数待会进行判断时要用到的,为了避免大家看不懂,先在这里进行说明
现在,我们按照刚才说的步骤来一步一步实现代码:
1.当轮到的a[i]的是数子时,直接输出出来;
if (a[i]>='0'&&a[i]<='9')
cout << a[i];
else if (a[i] == '(')
ITP.push_back(a[i]);
2.当读取的是运算符时,不直接输出,先入栈存储(存储是针对栈中无其他运算符),然后进行优先级的比较:
1)如果该运算符的优先级比栈顶元素(即运算符或者左括号,这个之后再说)的要高,那么就入栈;
2)如果该运算符的优先级没有栈顶的高,那么栈顶的操作符就输出来并出栈,再接着拿当前栈顶操作符的优先级与待入栈的元素a[i]进行比较,以此类推;直到,,,,(第三步)
if (!ITP.empty()&&(ITP.at(ITP.size()-1)== '+'
|| ITP.at(ITP.size() - 1) == '-' ||
ITP.at(ITP.size() - 1) == '*' ||
ITP.at(ITP.size() - 1) == '/'))//这样保证刚开始时进来的和顶上的全是运算元
{
t1 = pr(a[i]);
t2 = pr(ITP.at(ITP.size() - 1));
if (t2 == -2)//
{
cout << "System mistake!" << endl;
return 0;
}
else if (t2 >= t1 )
{
while (!ITP.empty())//&&ITP.back()!='(')//&& ITP.at(ITP.size() - 1) != '(')
{
t1 = pr(a[i]);
t2 = pr(ITP.at(ITP.size() - 1));
if (ITP.back() != '('&&t2>=t1)
{
cout << ITP.at(ITP.size() - 1);
ITP.pop_back();
}
else if (t2 < t1)//防止这个a[i]可能入栈失败
{
ITP.push_back(a[i]);
break;
}
else if (ITP.back() == '(')
{
ITP.push_back(a[i]);
break;
}
}
4.如果读取到的运算符为“)”,那么直接输出栈中元素,并从栈中弹出运算符,直到遇到“(”,“(”和“)”不用输出;
else if (a[i] == '(')
ITP.push_back(a[i]);
else if(a[i]==')')
{
while (ITP.back() != '('&&!ITP.empty())//vetor.at(vetor.size() - 1)
{
cout << ITP.at(ITP.size() - 1);
ITP.pop_back();
}
}
5.当字符串全部读取过一遍后,将栈中的运算符按序全部输出再弹出(除了“(”),直到!s.empty()的值为假
while(!ITP.empty())
{
//cout <<" "<< ITP.back() << endl;
//ITP.pop_back();
if (ITP.back() != '(')
{
cout << ITP.at(ITP.size() - 1) ;
ITP.pop_back();
}
else if(ITP.back()=='(')
{
ITP.pop_back();
}
}
直到这里,基本的代码段就完成了,下面是完整的代码段(字符串a 我的设计方法是只接受实数和运算符的输入如果是要其他条件,大家可以自行更改代码),以下代码在VS2017上编译通过!
#include "pch.h"
#include <iostream>
#include<string>
#include<vector>
using namespace std;
int pr(char ch)
{
if (ch == '*' || ch == '/')
return 1;
if (ch == '+' || ch == '-')
return 0;
if (ch == '(')
return -1;
else
return -2;
}
//string infixTopostfix(const string&express)
int main()
{
int t1=0,t2=0;
vector<char>ITP;
string a;
a="(1+2)*(3+4)";
for (unsigned int i = 0; i < a.length(); i++)
{
if (a[i]>='0'&&a[i]<='9')
cout << a[i];
else if (a[i] == '(')
ITP.push_back(a[i]);
else if(a[i]==')')
{
while (ITP.back() != '('&&!ITP.empty())//vetor.at(vetor.size() - 1)
{
cout << ITP.at(ITP.size() - 1);
ITP.pop_back();
}
}
else if (a[i] == '+' || a[i] == '-' || a[i] == '*' || a[i] == '/')
{
if (!ITP.empty()&&(ITP.at(ITP.size()-1)== '+'
|| ITP.at(ITP.size() - 1) == '-' ||
ITP.at(ITP.size() - 1) == '*' ||
ITP.at(ITP.size() - 1) == '/'))//这样保证刚开始时进来的和顶上的全是运算元
{
t1 = pr(a[i]);
t2 = pr(ITP.at(ITP.size() - 1));
if (t2 == -2)//
{
cout << "System mistake!" << endl;
return 0;
}
else if (t2 >= t1 )
{
while (!ITP.empty())//&&ITP.back()!='(')//&& ITP.at(ITP.size() - 1) != '(')
{
t1 = pr(a[i]);
t2 = pr(ITP.at(ITP.size() - 1));
if (ITP.back() != '('&&t2>=t1)
{
cout << ITP.at(ITP.size() - 1);
ITP.pop_back();
}
else if (t2 < t1)//防止这个a[i]可能入栈失败
{
ITP.push_back(a[i]);
break;
}
else if (ITP.back() == '(')
{
ITP.push_back(a[i]);
break;
}
}
if (ITP.empty())
{
ITP.push_back(a[i]);
}
}
else
{
ITP.push_back(a[i]);
}
}
else
{
ITP.push_back(a[i]);
}
}
}
while(!ITP.empty())
{
//cout <<" "<< ITP.back() << endl;
//ITP.pop_back();
if (ITP.back() != '(')
{
cout << ITP.at(ITP.size() - 1) ;
ITP.pop_back();
}
else if(ITP.back()=='(')
{
ITP.pop_back();
}
}
return 0;
}
附:感谢这个博文给我的启发,大家看不懂的话可以看看这个,还蛮好的
链接:https://www.cnblogs.com/libra-yong/p/6360114.html
有关于中序转后序的题目大家可以参照我的一篇文章:https://blog.csdn.net/CHINA_CNN/article/details/89344019