用栈实现中缀表达式到后缀表达式的转变--------C++实现(详解)

变换规则

从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为中缀表达式的一部分;若是符号,则判断符号的优先级,是右括号或者优先级不高于栈顶符号的优先级(乘除优先于加减),则栈顶元素一次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。

规则具体解释

一、若是数字,就直接输出,这个没啥问题。

二、如果符号就分情况:

  1. 若符号为  左括号( ,就直接入栈。
  2. 若符号为  右括号 ),那就去遍历栈,写一个循环依次去遍历栈顶元素,如果栈顶元素不是左括号 (  。那么就把栈顶元素输出,继续按照前面的规则去遍历栈。等到循环结束,那这时候栈顶元素就是右括号了,然后再将栈顶元素出栈即可。
  3. 若符号为 +  或者  -  。那就去遍历栈(还是写一个循环),首先判断栈是否为空(一开始我就忘记判断了,最后导致程序直接崩溃了)。如果栈不为空,就那就判断栈顶元素是否为左括号 (  。如果不是左括号,那就把栈顶元素出栈(不论栈顶元素是什么符号,因为 + 或者 - 的优先级永远不高于+ - * /)。直到栈空或者遇到了左括号为止。等到循环结束再把这个符号入栈就可以了。
  4. 若符号为 * 或者 / 。那么还是去遍历栈,首先判断栈是否为空。如果栈不为空,那就判断栈顶元素,如果栈顶元素为 * 或者 /。那就继续遍历栈,知道不满足条件位置。然后再把这个符号入栈即可
  5. 等到中缀表达式遍历结束,就再遍历一遍栈,把栈内的元素全部输出。

样例

          中缀表达式:9+(3-1)*3+10/2

样例详解

  1. 数字9输出
  2. 符号 +   入栈    ,此时栈内元素 +。
  3. 符号(  入栈    ,此时栈内元素 +  (  。
  4. 数字3输出
  5. 符号  -  入栈    , 此时栈内元素 +  (   -   。
  6. 数字 1 输出
  7. 符号 )。把  栈内的 -  号出栈并输出。再把(   出栈 。。     此时栈内元素 +    。
  8. 符号  *   。入栈     ,   此时栈内元素 +   *  。
  9. 数字3输出
  10. 符号 +  。 把栈内的  *  和  +  出栈,然后这个 + 号入栈。    此时栈内元素   +   。
  11. 数字10入栈
  12. 符号 /  。入栈    ,   此时栈内元素   +   /  。
  13. 数字2输出
  14. 再把栈内的 /  和 + 都出栈   。。。最后栈空了

最终输出结果

              9  3  1  -  3  *  +  10  2 / +

代码实现过程

我的代码实现过程利用我后缀表达式的代码思想。有兴趣的可以点击下面的连接了解一下。

https://blog.csdn.net/weixin_44820625/article/details/106587290

实现思路

  1. 比如想数字11 和数字2 ,一个是两位数,一个数一位数,输出结果的话肯定要加以区分,因为如果不区分,112这样就没法区分是11  和2还是1  和12之类的了。这一采取区分的方法就是没输出一个数或一个符号是,就在输出一个空格,这样等后期再用输出的结果时,就可以根据空格来区分了
  2. 在代码中我是用函数实现的中缀表达式变成后缀表达式的过程,传入参数是一个字符串,就是中缀表达式,函数的返回值类型也是string类型。返回的就是 转变成后的  后缀表达式
  3. 其中用到了find_first_of函数,如果不会用,可以先去学一下这个函数怎么使用的了。
  4. 至于剩下的就是利用if else  来把上面说的中缀表达式转后缀表达式的规则实现出来的,具体看代码

C++代码实现

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

//中缀表达式转后缀表达式函数
string change(const string str)
{
	stack<char> mystack;
	string strTarget;
	string ch = "+-*/()";
	string s = "0123456789+-*/()";
	string tempstr;
	int start, end;
	for (int i = 0; i < str.length(); i=end)
	{
		start = i;
		end = str.find_first_of(ch, i);//肯定是一个符号
		if (start == end)
		{
			tempstr = str.substr(start, 1);
			end++;
		}
		else
		{
			if (end == -1)//处理遍历到最后的情况
			{
				end = str.length();
			}
			tempstr = str.substr(start, end - start);
		}

		if (tempstr == "(")//左括号
		{
			char c = '(';
			mystack.push(c);
		}
		else if(tempstr ==")" )//右括号
		{
			while ( mystack.top() != '(')
			{
				strTarget += mystack.top();
				strTarget += " ";
				mystack.pop();
			}
			mystack.pop();//右括号出栈
		}
		else if ((tempstr == "+") || (tempstr == "-"))
		{
			while ((mystack.empty() != true) && (mystack.top() != '(') )
			{
				strTarget += mystack.top();
				strTarget += " ";
				mystack.pop();
			}
			char c = tempstr[0];
			mystack.push(c);
		}
		else if ((tempstr == "*") || (tempstr == "/"))
		{
			while ((mystack.empty() != true) && ((mystack.top() == '*') || (mystack.top() == '/')))
			{
				strTarget += mystack.top();
				strTarget += " ";
				mystack.pop();
			}
			char c = tempstr[0];
			mystack.push(c);
		} 
		else//数字
		{
			strTarget += tempstr;
			strTarget += " ";
		}
	}
	while (mystack.empty() != true)
	{
		strTarget += mystack.top();
		strTarget += " ";
		mystack.pop();
	}
	return strTarget;
}


int main()
{
	string str;
	string ans;//用来接受转换后的后缀表达式
	getline(cin, str);
	ans = change(str);
	cout << ans << endl;
	system("pause");
	return 0;
}

最后再说一点,上面的代码实现了中缀表达式转成后缀表达式的过程,如果想把转成的后缀表达式计算出来,可以看看我下面的链接

https://blog.csdn.net/weixin_44820625/article/details/106587290

猜你喜欢

转载自blog.csdn.net/weixin_44820625/article/details/106592806