【数据结构】中缀表达式转前缀表达式,后缀表达式 【详解】【代码】【考研】

本文详细介绍了前缀表达式(波兰表示法)、中缀表达式和后缀表达式(逆波兰表示法)的概念,并提供了中缀表达式转换为后缀表达式的步骤和实例解析。通过具体的操作步骤和代码实现,帮助读者理解转换过程。同时,讲解了解决此类问题的整体策略和关键步骤,适用于解决复杂表达式的转换问题。
摘要由CSDN通过智能技术生成

前缀表达式,中缀表达式,后缀表达式

概念

  1. 前缀表达式:波兰表示法:操作符置于操作数前面(+ab
  2. 中缀表达式:操作符置于操作数之间(a+b)
  3. 后缀表达式:逆波兰表示法:操作符置于操作数后面(ab+

核心思想:操作符置于操作数的位置。当中缀需要转换时,因为运算符的位置改变,需要先将运算符暂存起来,使用栈结构


中缀转后缀

  1. 从左到右扫描表达式
  2. 遇到操作数直接输出,输出顺序从左到右
  3. 遇到操作符
    1. 操作符为:“(” / 优先级>栈顶符号 / 栈为空 ⇒ 入栈
    2. 操作符为:优先级<=栈顶符号 ⇒ 栈顶出栈。并再次与栈顶比较
  4. 遇到括号
    1. 括号为:”(” ⇒ 入栈
    2. 括号为:”)” ⇒ 依次弹出栈顶符号,直到遇到 “(”,然后丢弃这一对括号
  5. 将栈中剩余的操作符依次弹出,输出顺序从左到右

中缀转前缀

  1. 从右到左扫描表达式
  2. 遇到操作数直接输出,输出顺序从右到左
  3. 遇到操作符
    1. 操作符为:“)” / 优先级>=栈顶符号 / 栈为空 ⇒ 入栈
    2. 操作符为:优先级<栈顶符号 ⇒ 栈顶出栈。并再次与栈顶比较
  4. 遇到括号
    1. 括号为:”)” ⇒ 入栈
    2. 括号为:”(” ⇒ 依次弹出栈顶符号,直到遇到 “)”,然后丢弃这一对括号
  5. 将栈中剩余的操作符依次弹出,输出顺序从右到左

做题方法

(1)要有整体的感觉

在解这类问题时,需要有整体的感觉,a+b把这里的a和b看作是一个表达式,作为一个整体,比如a*b+c*d,就是把a*b看作一个整体,把c*d看作一个整体。
例如:假如有括号形式,(a+b+c)*d这里的整体就是(a+b+c)d

  1. 将前面这一部分设为A,写成后缀表达式就是Ad*
  2. 然后再将A这一个整体继续拆a+b+c,运算顺序是先a+b再+c,所以先将a+b看作一个整体B,写为后缀表达式为Bc+
  3. 最后将a+b写为ab+

最终结果就是ab+c+d*
对于简单的问题,可以眼瞅出来做的,但对于复杂一些的问题,就不是这么容易了,就需要用更加系统的方法

(2)中缀转后缀的操作步骤

例如:a+b-a*((c+d)/e-f)+g(2012年408真题),将这个中缀表达式转换为后缀表达式,手写需要写两行:输出,栈。一个写当前输出的内容,一个写栈中存储的内容。主要的原则就是按照上面介绍的中缀转后缀步骤,一步步操作,多做几次就熟练了,下面详细写一个每步操作的介绍。

当然,自己在草稿纸上手写的话,就可以捋着中缀表达式来,心里清楚对于扫描到的每个元素是该怎么操作就行

  1. 从左到右扫
    a+b-a*((c+d)/e-f)+g
步骤当前符号栈内符号操作判断当前操作输出结果
1a操作数→直接输出输出aa
2+操作符→栈空→入栈+入栈a
3b+操作数→直接输出输出bab
4-+优先级-=+→+出栈输出+ab+
-操作符→栈空→入栈-入栈ab+
5a-操作数→直接输出输出aab+a
6*-优先级*>-→*入栈*入栈ab+a
7(-*左括号→入栈(入栈ab+a
8(-*(左括号→入栈(入栈ab+a
9c-*((操作数→直接输出输出cab+ac
10+-*((栈顶为左括号→入栈+入栈ab+ac
11d-*((+操作数→直接输出输出dab+acd
12)-*((+右括号→出栈,直到遇到(输出+ab+acd+
)-*((遇到(,丢弃这对括号(出栈,并丢弃ab+acd+
13/-*(栈顶为左括号→入栈/入栈ab+acd+
14e-*(/操作数→直接输出输出eab+acd+e
15--*(/优先级-</→/出栈输出/ab+acd+e/
--*(栈顶为左括号→入栈-入栈ab+acd+e/
16f-*(-操作数→直接输出输出fab+acd+e/f
17)-*(-右括号→出栈,直到遇到(输出-ab+acd+e/f-
)-*(遇到(,丢弃这对括号(出栈,并丢弃ab+acd+e/f-
18+-*优先级+<出栈输出*ab+acd+e/f-*
+-优先级-=+→-出栈输出-ab+acd+e/f-*-
+操作符→栈空→入栈+入栈ab+acd+e/f-*-
19g+操作数→直接输出输出gab+acd+e/f-*-g
20+将栈中剩余元素依次弹出输出+ab+acd+e/f-*-g+

配合着这个步骤表进行理解,不要生搬硬套这个表,要以前面讲的具体操作步骤来做


代码

#include<iostream>
#include<stack>
#include<string>
#include<algorithm>
#include<map>

using std::stack;
using std::cout;
using std::endl;
using std::string;
using std::map;

// 定义运算符优先级,'('要压入栈,比较优先级,所以应该添加进来
map<char, int> prior = { {'*',3 }, {'/',3}, {'+',2}, {'-',2},{'(',1} };

string trans(const string& mid_str)
{
	string end_str{ "" };
	stack<char> s;
	std::for_each(std::begin(mid_str), std::end(mid_str),
		[&](const char c) {
			// 操作数->直接输出
			if (prior.find(c) == prior.end() && c != ')') {
				end_str += c;
				return;
			}

			// 操作符->和栈顶比较
			else if (prior.find(c) != prior.end()) {
				// 操作符优先级>栈顶 -> 入栈
				// 栈为空 -> 入栈
				// 栈顶为'(' -> 入栈
				// 操作符为'(' -> 入栈
				if (s.empty() || prior[c] > prior[s.top()] || c == '(') {
					s.push(c);
					return;
				}

				// 操作符优先级<=栈顶 -> 出栈,并再次比较
				while (prior[c] <= prior[s.top()]) {
					end_str += s.top();
					s.pop();
					if (s.empty() || prior[c] > prior[s.top()]) {
						s.push(c);
						return;
					}
				}
			}

			// 右括号->出栈,直到遇到')',并丢弃这对括号
			else if (c == ')') {
				while (s.top() != '(') {
					end_str += s.top();
					s.pop();
				}
				s.pop();  // 丢弃左括号
				return;
			}

		});  // 扫描完整个串


	// 扫描完字符串,弹出剩余元素
	while (!s.empty()) {
		end_str += s.top();
		s.pop();
	}
	return end_str;
}

int main()
{
	string mid_str = "a+b-a*((c+d)/e-f)+g";
	cout << "转换前的中缀表达式: " << mid_str << endl;

	auto res = trans(mid_str);
	cout << "转换后的后缀表达式: " << res << endl;
}
  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
中缀表达式是我们常见的数学表达式的一种写法,它是以操作符位于操作数的两侧的形式来表示计算顺序。而前缀表达式后缀表达式中缀表达式的另外两种等价的写法。 将中缀表达式换为前缀表达式的方法如下: 1. 从右到左遍历中缀表达式的每个字符。 2. 如果字符是操作数,直接输出到前缀表达式。 3. 如果字符是操作符,有两种情况: - 如果操作符的优先级比栈顶操作符的优先级高,将操作符入栈。 - 如果操作符的优先级比栈顶操作符的优先级低或相等,弹出栈顶操作符,并将弹出的操作符和操作数组合为一个前缀表达式,再将该前缀表达式入栈。 4. 当遍历完中缀表达式后,将栈中的操作符依次弹出,并将每个弹出的操作符和操作数组合为一个前缀表达式,再将该前缀表达式入栈。 5. 最后得到的栈顶即为换后的前缀表达式。 将中缀表达式换为后缀表达式的方法基本相同,只需将步骤3中操作符的优先级比较符号调整为"低或相等"即可。 中缀表达式后缀表达式的方法如下: 1. 从左到右遍历中缀表达式的每个字符。 2. 如果字符是操作数,直接输出到后缀表达式。 3. 如果字符是操作符,有两种情况: - 如果操作符的优先级比栈顶操作符的优先级高或栈为空,将操作符入栈。 - 如果操作符的优先级比栈顶操作符的优先级低或相等,弹出栈顶操作符,并将弹出的操作符和操作数组合为一个后缀表达式,再将该后缀表达式入栈。 4. 当遍历完中缀表达式后,将栈中的操作符依次弹出,并将每个弹出的操作符和操作数组合为一个后缀表达式,再将该后缀表达式入栈。 5. 最后得到的栈顶即为换后的后缀表达式。 通过上述步骤,我们可以将中缀表达式换为前缀和后缀表达式
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值