变换规则
从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为中缀表达式的一部分;若是符号,则判断符号的优先级,是右括号或者优先级不高于栈顶符号的优先级(乘除优先于加减),则栈顶元素一次出栈并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。
规则具体解释
一、若是数字,就直接输出,这个没啥问题。
二、如果符号就分情况:
- 若符号为 左括号( ,就直接入栈。
- 若符号为 右括号 ),那就去遍历栈,写一个循环依次去遍历栈顶元素,如果栈顶元素不是左括号 ( 。那么就把栈顶元素输出,继续按照前面的规则去遍历栈。等到循环结束,那这时候栈顶元素就是右括号了,然后再将栈顶元素出栈即可。
- 若符号为 + 或者 - 。那就去遍历栈(还是写一个循环),首先判断栈是否为空(一开始我就忘记判断了,最后导致程序直接崩溃了)。如果栈不为空,就那就判断栈顶元素是否为左括号 ( 。如果不是左括号,那就把栈顶元素出栈(不论栈顶元素是什么符号,因为 + 或者 - 的优先级永远不高于+ - * /)。直到栈空或者遇到了左括号为止。等到循环结束再把这个符号入栈就可以了。
- 若符号为 * 或者 / 。那么还是去遍历栈,首先判断栈是否为空。如果栈不为空,那就判断栈顶元素,如果栈顶元素为 * 或者 /。那就继续遍历栈,知道不满足条件位置。然后再把这个符号入栈即可
- 等到中缀表达式遍历结束,就再遍历一遍栈,把栈内的元素全部输出。
样例
中缀表达式:9+(3-1)*3+10/2
样例详解
- 数字9输出
- 符号 + 入栈 ,此时栈内元素 +。
- 符号( 入栈 ,此时栈内元素 + ( 。
- 数字3输出
- 符号 - 入栈 , 此时栈内元素 + ( - 。
- 数字 1 输出
- 符号 )。把 栈内的 - 号出栈并输出。再把( 出栈 。。 此时栈内元素 + 。
- 符号 * 。入栈 , 此时栈内元素 + * 。
- 数字3输出
- 符号 + 。 把栈内的 * 和 + 出栈,然后这个 + 号入栈。 此时栈内元素 + 。
- 数字10入栈
- 符号 / 。入栈 , 此时栈内元素 + / 。
- 数字2输出
- 再把栈内的 / 和 + 都出栈 。。。最后栈空了
最终输出结果
9 3 1 - 3 * + 10 2 / +
代码实现过程
我的代码实现过程利用我后缀表达式的代码思想。有兴趣的可以点击下面的连接了解一下。
https://blog.csdn.net/weixin_44820625/article/details/106587290
实现思路
- 比如想数字11 和数字2 ,一个是两位数,一个数一位数,输出结果的话肯定要加以区分,因为如果不区分,112这样就没法区分是11 和2还是1 和12之类的了。这一采取区分的方法就是没输出一个数或一个符号是,就在输出一个空格,这样等后期再用输出的结果时,就可以根据空格来区分了
- 在代码中我是用函数实现的中缀表达式变成后缀表达式的过程,传入参数是一个字符串,就是中缀表达式,函数的返回值类型也是string类型。返回的就是 转变成后的 后缀表达式
- 其中用到了find_first_of函数,如果不会用,可以先去学一下这个函数怎么使用的了。
- 至于剩下的就是利用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