中缀转后缀表达式并计算

注:本博客是基于《数据结构》这门课,主要是为了自己考研,准备专业课
图解转自:中缀转后缀算法

中缀转后缀算法

中缀表达式转后缀表达式遵循以下原则:

  1. 遇到操作数,直接输出
  2. 当栈为空时,若遇到运算符,则入栈
  3. 当遇到左括号 “(” 时,则将其入栈
  4. 当遇到右括号 “)” 时,执行出栈操作,将栈顶的元素输出,直到栈顶元素是左括号时弹出并停止,左括号不输出
  5. 当遇到其他运算符如“+”、“-”、“ * ” 、“ / ”时,弹出栈中所有优先级大于或等于该运算符的栈顶元素,然后将该运算符入栈
  6. 最后,再将栈中的元素依次出栈,输出
  7. 经过上面的步骤,得到的输出既是转换得到的后缀表达式

⚠️ 运算符优先级: { *,/ } > { +,— } > { ( }

举例:a+b * c+(d * e+f) * g ——> abc * +de * f+g * +

图示上述过程:

遇到a,直接输出:

在这里插入图片描述
遇到+,此时栈为空,入栈:

这里写图片描述
遇到b,直接输出:

这里写图片描述
遇到*,此时其优先级大于栈顶符号+的优先级,则入栈:
遇到c,输出:

这里写图片描述

遇到+,目前站内的* 、+优先级都大于或等于它,因此将栈内的* 、+依次弹出并且输出,并且将这个+入栈:

这里写图片描述

遇到(,将其入栈:

在这里插入图片描述
遇到d,直接输出:

在这里插入图片描述

遇到*,由于其优先级高于处在栈顶的(,因此直接入栈:

在这里插入图片描述

遇到e,直接输出:

在这里插入图片描述
遇到+,此时栈顶的*优先级高于+,但是栈内的( 优先级低于 +,故将 * 出栈输出,+入栈:

在这里插入图片描述
遇到f,直接输出:

在这里插入图片描述
遇到 ),弹出栈顶元素并且输出,直到遇到( 才结束,在这里也就是弹出+输出,弹出(不输出:

在这里插入图片描述
遇到*,优先级高于栈顶+,将*入栈

在这里插入图片描述

遇到g,直接输出:

在这里插入图片描述
此时中缀表达式已全部处理完成,故依次将栈中元素出栈并输出,直到栈为空:

在这里插入图片描述
代码部分:

//中缀表达式转后缀表达式
#include<iostream>
#include<string>
#include<stack>

using namespace std;

int prio(char op) {                 //给运算符优先级排序
	int priority=0;
	if (op == '*' || op == '/')
		priority = 2;
	if (op == '+' || op == '-')
		priority = 1;
	if (op == '(')
		priority = 0;
	return priority;
}

bool Trans(string& str1, string& str2) {   //引用传递
	stack<char> s;                   //定义一个char类型的栈s
	int i;
	for (i = 0; i < str1.size(); i++) 
	{
		if (str1[i] >= '0' && str1[i] <= '9') {    //如果是数字,直接入栈
			str2 += str1[i];
		}
		else		//否则不是数字
		{                       
			if (s.empty())            //栈空则入站
				s.push(str1[i]);
			else if (str1[i] == '(')   //左括号入栈
				s.push(str1[i]);
			else if (str1[i] == ')') {  //如果是右括号,只要栈顶不是左括号,就弹出并输出
				while (s.top() != '(') {
					str2 += s.top();
					s.pop();
				}
				s.pop();                 //弹出左括号,但不输出
			}
			else {		//当栈顶非空时
				while (prio(str1[i]) <= prio(s.top())) { //当栈顶优先级大于等于当前运算符,输出
					str2 += s.top();
					s.pop();
					if (s.empty())      //栈为空,停止
						break;
				}
				s.push(str1[i]);   //把当前运算符入栈
			}
		}
	}
	while (!s.empty()) {      //最后,如果栈不空,则弹出所有元素并输出
		str2 += s.top();
		s.pop();
	}
	return true;
}

int main() {                //主程序
	string infix;	//保存输入的中缀表达式
	string postfix;		
	cout << "请输入中缀表达式:" << infix << endl;
	cin >> infix;
	Trans(infix, postfix);
	cout << "后缀表达式为:" << postfix << endl;
	system("pause");
	return 0;
}

后缀表达式计算思路:

从左往右依次扫描后缀表达式,遇到操作数入栈,遇到运算符、则弹出两个操作数、计算结果并将结果入栈( 注:先弹出的为右操作数,后弹出的为左操作数),循环以上过程,直到扫描完后缀表达式,此时栈中的数即为运算结果。
图解:

实例:

输入: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"]
输出: 22
解释: 
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

具体实现:

class Solution {
public:
     int evalRPN(vector<string>& tokens) {
        stack<int> numbers;
        for(int i = 0 ; i < tokens.size() ;i++){
            //若为运算符,则弹出两个栈顶元素,进行运算并将结果放回栈
            if(tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/"){
                int res;
                int n2 = numbers.top();
                numbers.pop();
                int n1 = numbers.top();
                numbers.pop();
                
                if(tokens[i] == "+")
                   res = n1 + n2;
                else if(tokens[i] == "-")
                   res = n1 - n2;
                else if(tokens[i] == "/")
                   res = n1 / n2;
                else
                   res = n1 * n2;
                numbers.push(res);
            }else{
                //若为运算数,则直接入栈
                numbers.push(tokens[i]);
            } 
        }
        return numbers.top();
    }
};
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值