C++ DS栈—波兰式,逆波兰式


一、题目描述

表达式有三种表示方法,分别为:

前缀表示(波兰式):运算符+操作数1+操作数2
中缀表示:操作数1+运算符+操作数2
后缀表示(逆波兰式):操作数1+操作数2+运算符
例如:a +b * (c -d ) - e/f

波兰式:-+ab-cd/ef (运算符在操作数的前面,用递归计算波兰式)
中缀式:a+b
c-d-e/f
逆波兰式:abcd-*+ef/- (运算符在操作数的后面,用栈计算逆波兰式)
中缀表示就是原表达式去掉括号。

根据表达式求波兰式、逆波兰式都是教材第三章表达式求值的思想。

求波兰式,需要操作数栈(注意不是计算结果入栈,计算式入栈),运算符栈。区别在于从后往前扫描表达式,( 换成 )。栈顶运算符优先级>新读入运算符优先级出栈,教材第三章表3.1中的相同运算符优先级>(从左往右计算)改为<,例如栈顶为+,新读入的为+,则栈顶优先级<新读入的优先级。

求逆波兰式,只需要运算符栈。操作数直接输出,操作符按表3.1优先级顺序出栈,输出。

输入表达式,求其波兰式和逆波兰式。


二、输入与输出

1.输入

测试次数

每组测试数据一行,一个合法表达式

2
4+2*3-10/5
12+3*5+(2+10)*5 

2.输出

对每组测试数据,输出两行

第一行,表达式的波兰表示

第二行,表达式的逆波兰表示

不同组测试数据间以空行分隔。

- + 4 * 2 3 / 10 5
4 2 3 * + 10 5 / -

+ + 12 * 3 5 * + 2 10 5
12 3 5 * + 2 10 + 5 * +

三、参考代码

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

bool opr(char op1, char op2) {
	if (op1 == '+' || op1 == '-') 
	{
		return op2 == '+' || op2 == '-';
	}
	return true;
}

bool opl(char op1, char op2) {
	if (op1 == '*' || op1 == '/') {
		return op2 != '*' && op2 != '/';
	}
	return false;
}

class polan {

private:

	stack<string> nums;
	stack<char> op;
public:

	string po1(string str)
	{
		int len = str.length();
		//cout << len << endl;
		for (int i = len - 1; i >= 0; --i) 
		{

			if (str[i] >= '0' && str[i] <= '9' ) {

				string num = "";
				num += str[i];
				while (i - 1 >= 0 && str[i - 1] <= '9' && str[i - 1] >= '0'  )
				{
					num = str[--i] + num;
				}
				nums.push(num);
			}
			else if(op.empty() || str[i]==')' || op.top() == ')'  )
			{
				op.push(str[i]);
			}
			else if (str[i] == '(') 
			{
				while (!op.empty() && op.top() != ')')
				{
					string ops = "";
					ops += op.top();
					nums.push(ops);
					op.pop();
				}
				op.pop();
			}
			else if(opr(str[i],op.top()))
			{
				op.push(str[i]);
			}
			else
			{
				while (!op.empty() && !opr(str[i], op.top()))
				{
					string ops = "";
					ops += op.top();
					nums.push(ops);
					op.pop();
				}
				op.push(str[i]);
			}
		}
		while (!op.empty())
		{
			string ops = "";
			ops += op.top();
			nums.push(ops);
			op.pop();
		}

		string putout = "";
		while (!nums.empty())
		{
			putout += nums.top() + (nums.size() > 1 ? " " : "");
			nums.pop();
		}
		return putout;
	}

	string po2(string str)
	{
		int len = str.length();
		string putout = "";
		//cout << len << endl;
		for (int i = 0; i < len; ++i) 
		{

			if (str[i] <= '9' && str[i] >= '0') {
				
				putout += str[i];
				while (str[i + 1] <= '9' && str[i + 1] >= '0' && i + 1 < len)
				{
					putout += str[++i];
				}
				putout += " ";
			}
			else if (op.empty() || str[i] == '(' || op.top() == '(')
			{
				op.push(str[i]);
			}
			else if (str[i] == ')')
			{
				while (!op.empty() && op.top() != '(')
				{
					putout += op.top();
					putout += " ";
					op.pop();
				}
				op.pop();
			}
			else if (opl(str[i], op.top()))
			{
				op.push(str[i]);
			}
			else
			{
				while (!op.empty() && !opl(str[i], op.top()))
				{
					putout += op.top();
					putout += " ";
					op.pop();
				}
				op.push(str[i]);
			}
		}
		while (!op.empty())
		{
			putout += op.top();
			putout += (op.size() > 1 ? " " : "");
			op.pop();
		}
		return putout;
	}

};


int main() {

	int sum;
	cin >> sum;
	while (sum--)
	{
		polan p; 
		string str;
		cin >> str;
	
		cout << p.po1(str) << endl;
		cout << p.po2(str) << endl;
		cout << endl;
	}

	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Z1Jxxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值