【数据结构学习】中缀表达式转后缀表达式

        后缀表达式,我们亦称其为逆波兰序数。在咱们编写计算器的时候,总会要用双栈模拟,进行计算。

       本题所描绘的中缀转后缀,只是很简单的转。并不能达到写计算器的目的,本文在此只用于个人的基础巩固,以及浅层次的思考,帮助进行中缀表达式转后缀表达式的理解。

      中缀表达式如1*2+(2-1),其运算符一般出现在操作数之间, 因此称为中缀表达式,也就是大家编程中写的表达式。编译系统不考虑表达式的优先级别,只是对表达式从左到右进行扫描, 当遇到运算符时, 就把其前面的两个操作数取出,进行运算操作。为达到上述目的, 就要将中缀表达式进行改写,变为后缀表达式, 如上面的表达式1*2+(2-1),就变为12*21-+。

      后缀表达式中不含有括号,且后缀表达式中的操作数排列次序和中缀表达式完全相同,这是运算符的次序发生了变化。我们实现的时候,便需要特定的数据结构(栈:stack),进行实现。

     其中的stack<char> op进行操作符的存储。string ans用来存放后缀表达式。

     接下来简述算法思想

       1)如果是‘(’则直接压入op栈。

       2)如果是‘)’,依次从op栈弹出运算符加到字符串ans的后面,直到遇到 '('。

       3)如果不是括号,则比较扫描到的运算符与op栈顶的运算符。如果扫描的运算符优先级高于栈顶运算符的优先级,便把扫描到的运算符压入栈中。若扫描的运算符优先级低于栈顶运算符的优先级,就依次把栈中运算符弹出加到字符串ans末尾,直到遇到的运算符优先级低于扫描到的运算符或者栈空,并把扫描到的运算符压入栈中。

      若扫描结束,则依次弹出添加到ans的末尾,便得到了后缀表达式。

 代码如下:

#include<iostream>
#include<cstring>
#include<stack>
using namespace std; 

int prior(char op) //运算符优先级 
{
	if(op == '+' || op == '-')
	{
		return 1;
	}
	else if(op == '*' || op == '/')
	{
		return 2;
	}
	return 0;
}

string middleToLast(string middle)
{
	stack<char> op;
	string ans;
	for(int i = 0; i < middle.size(); i++)
	{
		char c = middle[i];         //记录当前扫描字符 
		if(c >= '0' && c <= '9')
		{
			ans.append(1, c);      //如果是操作数,则直接添加到ans末尾 
		}
		else
		{
			if(c == '(')           //若遇到的是'('则直接压住栈中 
			{
				op.push('(');
			}
			else
			{	
				if(c == ')')      //如果遇到的是')' 
				{
					while(op.top() != '(') //没有遇到匹配的'(' 
					{
						ans.append(1, op.top()); //将栈顶运算符加到ans末尾 
						op.pop();        //将栈顶元素弹出 
					}
					op.pop();  //遇到了匹配的 '(' 跳出循环,并把'('弹出 
				}
				else
				{
					if(op.empty()) //如果栈空,直接压入当前运算符 
					{
						op.push(c);
					}
					else
					{
						if(prior(c) > op.top()) //如果当前运算符优先级高于栈顶运算符 
						{
							op.push(c);        //把当前运算符压入op栈中 
						}
						else
						{
							while( !op.empty() && prior(c) <= prior(op.top()) ) //若栈非空且当前运算符低于栈顶运算符优先级 
							{
								ans.append(1, op.top());  //栈顶字符加入到ans末尾 
								op.pop();         //弹出栈顶运算符 
							} 
							op.push(c);           //把当前运算符压入栈中 
						}
					}
				}
			}
		}
	}
	while( !op.empty() )  //若栈非空 
	{
		ans.append(1, op.top()); //把栈顶运算符添加到ans末尾 
		op.pop(); //弹出栈顶运算符 
	}
	return ans;
}

int main()
{
	string mdata, res;
	cin >> mdata;
	res = middleToLast(mdata);
	for(int i = 0; i < res.size(); i++)
	{
		cout << res[i] << " ";
	}
	return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值