数据结构---前缀中缀后缀表达式及其转换

前缀/中缀/后缀----表达式之间的相互转换_中缀表达式转前缀表达式-CSDN博客

一.基本定义

1.前缀

 前缀表达式,指的是不包含括号,运算符放在两个运算对象的前面,严格从右向左进行(不再考虑运算符的优先规则),所有的计算按运算符出现的顺序。

eg:

例如:中缀表达式 ( 2 + 3 ) × 4 - 5,采用前缀表达式为:- × + 2 3 4 5

13 * ((3 + 8) * 4),前缀表达式为 * 13 * + 3 8 4

2.后缀

同理

二:转换

1.中缀转换成后缀

#include<iostream>
#include<stack>
using namespace std;
bool isOperator(char c)
{
	if (c == '+' || c == '-' || c == '*' || c == '/')
		return 1;
	else return 0;
}
int Priority(char c)
{
	switch (c)
	{
	case '(':return 3; /注意这里数字越大优先级越低,(的优先级默认最低,可能跟常识不一样,仔细思考为什么,就会不在细讲了
	case '*':
	case '/':return 1; 
	case '+':
	case '-':return 2; 
	}
}
int main()
{
	int num = 0;
	char arr[100];
	char c;
	stack<char> op;//创建一个栈op
	while (1)//使程序一直循环,可以多次实现转换的功能
	{
		cin.getline(arr, 100);
		int i = 0;
		int len = (int)strlen(arr);//strlen返回的unsign int类型,需要强制转换为int
		while (i < len)//挨个处理字符
		{
			//首先是判断这个字符是数字还是括号还是运算符
			if (isdigit(arr[i]))//判断字符是否为数字,在库函数里,不用自己定义
			{
				num = 0;
				do
				{
					num = num * 10 + (arr[i] - '0');//num*10是存在多位数时使用   例如  38+90
					i++;
				} while (isdigit(arr[i]));
					cout << num ;
			}
			else if (arr[i] == '(')
			{
				op.push(arr[i]);
				i++;
			}
			else if (isOperator(arr[i]))
			{
				if (op.empty())//判断栈是不是空
				{
					//栈空,直接压栈
					op.push(arr[i]);
					i++;
				}
				// 比较栈op顶的操作符与ch的优先级
				// 如果ch的优先级高,则直接压入栈
				// 否则,推出栈中的操作符,直到操作符小于ch的优先级,或者遇到(,或者栈已空
				else//不空,判断优先级
				{
					while (!op.empty())//需要保证栈不能为空,因为栈为空的时候在进行比较等操作会出错,并且有可能需要弹出多个字符,需要while循环
					{
						 c = op.top();//将栈顶的元素拷贝给c
						if (Priority(arr[i]) < Priority(c))//arr[i]的优先级更大,直接压栈
						{			
							//这里不需要op.push(arr[i]);i++;因为这是在循环里,可能会把同一个字符多次压栈,所以放在循环外面
							break;
						}
						else
						{
							cout << c;
							op.pop();
						}
					}
					op.push(arr[i]);
					i++;
				}
			}
			
			else if (arr[i] == ')')
			{
				while (op.top() != '(')
				{
					//将栈中的运算符全部弹出,直到遇到‘(’
					cout << op.top();
					op.pop();
				}
				op.pop();
				i++;
			}
			else//如果是空字符,就直接处理下一个字符
			{
				i++;
			}
		}
		while (!op.empty())            //不要忘记栈中剩余的符号都弹出来
		{
			cout << op.top();
			op.pop();
		}
		cout << endl;
	}
}

遇到的问题或者错误:

1.关于符号的优先度

潜意识的就认为括号优先度最大,所以在求优先度的函数中把括号的优先度设成最大。这样是错误的!因为严格来说括号时不应该放在这个优先度比较的函数中的,只是因为某些原因(方便)

因为如果把括号的优先度调成最大的话:

看下面这种情况:

栈中(从上到下):(     +     *    -

此时对于正在处理的字符来说:如果的优先度最大,那么结果会把(弹出并打印出来,这样显然是不对的

2.关于while()循环


				else//不空,判断优先级
				{
					while (!op.empty())//需要保证栈不能为空,因为栈为空的时候在进行比较等操作会出错,并且有可能需要弹出多个字符,需要while循环
					{
						 c = op.top();//将栈顶的元素拷贝给c
						if (Priority(arr[i]) < Priority(c))//arr[i]的优先级更大,直接压栈
						{			
							//这里不需要op.push(arr[i]);i++;因为这是在循环里,可能会把同一个字符多次压栈,所以放在循环外面
							break;
						}
						else
						{
							cout << c;
							op.pop();
						}
					}
					op.push(arr[i]);
					i++;
				}
			

上面这一部分 的while循环,如果没有的话判断的每一个运算符只能弹出一个比他优先级高的运算符,弹出一个后新的栈顶元素的优先级依然大于这个运算符,这个时候也要把他弹出,所以要使用循环

3.最后一个while循环

负责把剩余的栈中的元素弹出来

拿最简单的例子:   

8  +  4

如果没有这个循环,那么转换后结果:

84

栈的知识巩固:

#include <stack>

stack <int> a;
stack <char> b;

//常用的函数
a.push(9);
b.push('*');
a.pop();
a.empty();



2.中缀转换成前缀

和后缀核心思想一样,就只是输出的顺序变了,输出的时候也类似一个栈

3.前缀转换成后缀

就是把前缀换成中缀在换成后缀

在数据结构的习题中有这一类题:

已知前缀和后缀的序列,画出树(不一定是二叉树)

先根:GFKDAIEBCHJ

后跟:DIAEKFCJHBG

这些是我自己猜测加总结:不一定准确

①确定根,即先根的第一个字母,后跟倒一个字母

②确定左子树:先根的第二个字母

③确定右子树:后跟的倒数第二个字母

④观察左子树再后跟中的位置,则它左面的都是根的左边,它的右面都是跟的右面

以此类推

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
为了回答你的问题,我将介绍前缀中缀后缀表达式,并展示如何在它们之间进行转换。 1. 前缀表达式(也称为波兰式): 在前缀表达式中,运算符位于操作数之前。例如,表达式 "2 + 3" 的前缀形式为 "+ 2 3"。 2. 中缀表达式: 中缀表达式是我们通常使用的常规数学表达式形式。它使用括号和运算符的优先级来表示运算顺序。例如,表达式 "2 + 3" 就是一个中缀表达式。 3. 后缀表达式(也称为逆波兰式): 在后缀表达式中,运算符位于相应的操作数之后。例如,表达式 "2 + 3" 的后缀形式为 "2 3 +"。 现在,我将向你展示如何将中缀表达式转换前缀后缀表达式。 从中缀前缀转换: 1. 反中缀表达式。 2. 将反中缀表达式转换后缀形式。 3. 反后缀表达式即可得到前缀表达式。 从中缀后缀转换: 1. 创建一个空栈和一个空输出列表。 2. 从左到右扫描中缀表达式的每个符号。 - 如果遇到操作数,将其添加到输出列表。 - 如果遇到运算符,将其压入栈中。 - 如果遇到左括号,将其压入栈中。 - 如果遇到右括号,则连续弹出栈顶元素并将其添加到输出列表,直到遇到左括号为止。注意:左括号不会被添加到输出列表中。 如果栈顶元素是左括号,则将其弹出栈。 - 如果遇到的运算符具有比栈顶运算符更高的优先级,将其压入栈中。 如果遇到的运算符具有与栈顶运算符相同的优先级,并且是左结合的运算符,则将栈顶运算符弹出并添加到输出列表中,然后将当前运算符压入栈中。 如果遇到的运算符具有与栈顶运算符相同的优先级,并且是右结合的运算符,则将当前运算符压入栈中。 - 重复步骤2直到扫描完整个中缀表达式。 3. 将栈中剩余的所有运算符弹出并添加到输出列表中。 4. 输出列表即为转换后的后缀表达式。 希望这个解释对你有帮助!如果你有其他问题,可以继续问我。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小布丁729

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

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

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

打赏作者

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

抵扣说明:

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

余额充值