利用栈转换中缀表达式到后缀表达式

本篇是栈篇的最后一篇,记录一下如何用栈实现中缀表达式转后缀表达式。
先举例一个后缀表达式9 3 1 – 2 * + 5 2 / + 他的中缀表达式是9+(3-1)*2+5/2
首先我们要找到这个表达式的优先级优先级最高的是括号 其次是乘法和除法再然后是加法 那么如何用栈来演示呢。
之前那个表达式很长难以理解,我们用A+(B*C)很明显B*\C的优先级高,所以把*置后 然后 A的操作数就变成了BC*
image.png
我们可以发现不管符号怎么后置,表达式的操作数的顺序都是不变的ABC 所以我们可以用一个字符串存放这些操作数,至于操作符我们发现只有找到他的右操作数时,表达式才会成立,也就可以置后操作符了。
image.png
如图,我们把操作数按次序放在了列表里,同时根据是否找到操作符的右操作数进行压栈操作,如果当前符号的优先级大于栈顶的符号,说明还没有找到这个优先级较大符号的有右操作数,如果当前符号小于栈顶的符号,说明已经找到了上一个符号的右操作数 比如A+B*C我们先不讨论括号+号已经入栈了,但是B后面是一个比+号优先级大的符号,难道我们要先算A+B吗 所以我们继续压栈,等到C之后没有符号了,说明C就是*的右操作数,分别pop *和+,再比如A*B+C,先入栈*,然后到下一个操作符判断和栈顶的优先级,很明显+号小于栈顶的*号,所以我们已经找到了最右操作数B,然后就可以在操作数列表里加入操作符了(后置),直接把栈顶的元素pop到字符串列表里,然后再把当前的操作符push到栈中,等待遍历其的右操作数。
我们直接用代码来说明,看看如何用代码实现。

#include<iostream>
#include<string>
#include<stack>
//不能友好显示十进制
//括号
using namespace std;
void infixtopostfix(string s);
bool Isnumber(char fix);
bool IsOperator(char c);
bool Hashigherpre(char top,char str);
int GetOperatorWeight(char op);
bool Isopening(char top);
int main()
{
	string line;
	printf("please input infix\n");
	getline(cin, line);
	infixtopostfix(line);
	return 0;
}

void infixtopostfix(string str)
{
	string fix;
	stack<char> S;
	int num = 0;
	for (size_t i = 0; i < str.length(); i++)
	{
		if (Isnumber(str[i]))
		{
			fix.push_back(str[i]);
		}
		else if (str[i]=='(')
		{
			S.push(str[i]);
		}
		else if (IsOperator(str[i]))
		{
			while (!S.empty()&& Hashigherpre(S.top(),str[i])&&!Isopening(S.top()))
			{
				fix += S.top();
				S.pop();

			}
			S.push(str[i]);
		}
		else if (str[i] == ')')
		{
			while (!S.empty()&& !Isopening(S.top()))
			{
				fix += S.top();
				S.pop();
			}
			S.pop();
		}

	}
	while (!S.empty())//表达式结束,操作符按顺序出栈
	{
		fix += S.top();
		S.pop();
	}
	cout << fix;
}

bool Isnumber(char fix)
{
	if (fix>='0' && fix <= '9')
	{
		return true;
	}
	return false;
}


bool IsOperator(char c)
{
	if (c == '+' || c == '-' || c == '*' || c == '/')
	{
		return true;
	}
	return false;
}

bool Hashigherpre(char top, char str)
{
	int weight01 = GetOperatorWeight(top);
	int weight02 = GetOperatorWeight(str);
	 return weight01 >= weight02 ? true : false;
}
int GetOperatorWeight(char op)

{

	int weight = -1;

	switch (op)

	{
	    case '+':
		case '-':
			weight = 1;
			break; 


	case '*':

	case '/':

		weight = 2;
		break;
	case '$':

		weight = 3;
		break;
	}

	return weight;

}

bool Isopening(char top)
{
	if (top == '(')
	{
		return true;
	}
	return false;
}

首先我们输入了中缀表达式之后,我们会用 string fix;存放我们新的后缀表达式,接着根据传入表达式的长度进入循环,如果是数字的话就加到字符串后面,如果是操作符的话,首先要看栈顶元素,如果栈不为空,而且当前操作符大于栈顶元素符号满足的话,就要push当前符号,如果不满足,就要把栈顶元素出栈,通过fix += S.top();S.pop();直到栈顶元素小于当前元素,执行push当前操作符,循环执行完成之后,如果栈内依然有元素的话,则需要把栈内元素都pop到表达式fix后面,这里再说一下括号,,毫无疑问,括号肯定是优先级最高的,所以我们遇到开放符号,先放入栈,然后等待右括号,如果等到右括号,说明已经找到右操作数了这时候就将括号里面的操作符按顺序出栈
看图

image.png

网站标题:CV鼻祖洋芋

原创文章,作者:locus,如若转载,请注明出处:https://blog.cvpotato.cn/forward-code/c-2/165/

本博客所发布的内容,部分为原创文章,转载注明来源,网络转载文章如有侵权请联系站长!

(0)
上一篇 2024年11月14日 下午6:33
下一篇 2024年11月14日 下午6:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注