中序转后序代码详解以及实现(C++)

前两天收到了一个作业题,讲的是把中序表达式表示成逆向波兰表达式,但是没理解,按照网上的方法做了下,搞了半天,发现总差一点,检查了一下代码,发现是在比较操作符优先级时出错了

下面对它的完整考虑方法

读入的括号必须是英文状态下的!

其算法的完整思路应该是:

  1. 当轮到的a[i]的是数子时,直接输出出来;
  2. 当读取的是运算符时,不直接输出,先入栈存储(存储是针对栈中无其他运算符),然后进行优先级的比较:

         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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值