中缀表示法转后缀表示法

题源:

PTA 数据结构2 习题3.11 表达式转换

题面没有讲的细节:

1.题面中出现‘\’来描述除号 但实际上是‘/’ 不会出现‘\’

2.操作数不一定是整数 可能会出现多位数 小数 负数 前面可能会出现无意义的正号来表示正负

        12,12.3,-12,+12都是可能出现的操作数

3.无意义的正号在输出时需要忽略掉 即使输入时有

        输入的 +12  输出时应只为 12

注意:

1.1 2和12是否区分

2.前文提及的细节是否处理

算法:

后缀表达式运算:

从左到右

遇到数字 直接入栈

遇到操作符 弹出两个数字 按照操作符运算得到结果 将结果入栈

中缀转后缀算法1:

从左到右遍历中缀表达式

遇到数字 直接输出

遇到操作符

若为‘(’ 直接入栈

若为‘ )’不断弹出元素并输出 直到弹出‘(’   注意!括号都不用输出!

若栈空 或 栈顶元素为括号 直接入栈

若操作符优先级大于栈顶元素优先级 直接入栈

否则 不断弹出栈顶元素并输出 直到栈顶元素为括号 或 栈空 或 操作符优先级大于栈顶元素优先级

之后再入栈

最后 弹出并输出栈顶元素 直到栈空

中缀转后缀算法2:

建表达式二叉树 后续遍历表达式树

建树方法:

1.优先级低 靠右的运算符离根近 优先优先级 同优先级优先靠右

2.自左向右使用数字 自左向右添加进叶节点中

后缀转中缀算法:

用表达式树 建树 中序遍历

ALL测试点AC的核心代码:

constexpr int MXN = 1e5 + 5;
char s[MXN];
stack<char> st;
queue<char> ans;
queue<str> q2;

bool CMP(char lhs, char rhs)
{
	if (lhs == '*' || lhs == '/')
		lhs = '2';
	else
		lhs = '1';
	if (rhs == '*' || rhs == '/')
		rhs = '2';
	else
		rhs = '1';
	return lhs > rhs;
}
void Solve(void)
{
	cin >> s + 1;
	ll len = strlen(s + 1);
	bool last = false;
	str num = "";
	ll cnt = 1;
	bool othFlag = false;
	char othChar;
	FOR(i, 1, len)
	{
		if (('0' <= s[i] && s[i] <= '9') || s[i] == '.')
		{
			if (last)
				num += s[i];
			else
			{
				num = "";
				num += s[i];
			}
			last = true;
			if (i == len)
			{
				if (othFlag&&othChar=='-')
				{
					num = othChar + num;
					othFlag = false;
				}
				q2.push(num);
				ans.push('n');
			}
			cnt = 0;
		}
		else
		{
			if (s[i] == '(')
				cnt = 1;
			else if (s[i] == ')')
				cnt = 0;
			else
				++cnt;
			if (cnt == 2)
			{
				othFlag = true;
				othChar = s[i];
				continue;
			}
			if (last)
			{
				if (othFlag&&othChar=='-')
				{
					num = othChar + num;
					othFlag = false;
				}
				q2.push(num);
				ans.push('n');
			}
			last = false;
			if (s[i] == '(')
				st.push(s[i]);
			else if (s[i] == ')')
				while (!st.empty())
				{
					if (st.top() == '(')
					{
						st.pop();
						break;
					}
					ans.push(st.top());
					st.pop();
				}
			else
			{
				if (st.empty() || st.top() == '(')
					st.push(s[i]);
				else if (CMP(s[i], st.top()))
					st.push(s[i]);
				else
				{
					while (!st.empty() && st.top() != '(' && CMP(s[i], st.top()) == false)
					{
						ans.push(st.top());
						st.pop();
					}
					st.push(s[i]);
				}
			}
		}
	}
	while (!st.empty())
	{
		ans.push(st.top());
		st.pop();
	}
	bool f = true;
	while (!ans.empty())
	{
		if (f)
			f = false;
		else
			cout << ' ';
		if (ans.front() != 'n')
			cout << ans.front();
		else
		{
			cout << q2.front();
			q2.pop();
		}
		ans.pop();
	}
	cout << edl;
	return;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值