LeetCode. 逆波兰表达式求值(后缀表达式 - 类似于树的后序遍历 // 中缀转前缀or后缀)

根据逆波兰表示法,求表达式的值。
有效的运算符包括 +, -, *, / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

示例 1:
输入: [“2”, “1”, “+”, “3”, “*”]
输出: 9
解释: ((2 + 1) * 3) = 9
示例 2:
输入: [“4”, “13”, “5”, “/”, “+”]
输出: 6
解释: (4 + (13 / 5)) = 6

后缀表达式,可以看作是一棵树的后序遍历,树的叶子节点均为操作数非叶子节点均为操作符号
中序遍历特征就是先看子节点 再看父节点
所以对于后缀表达式的解析,只需要一个栈来存取操作数
左→→→右遍历:
— 遇到操作数入栈
— 遇到操作符号则说明 该子树的孩子节点都遍历完了,回到了父节点了(后序遍历的逻辑),则将栈顶弹出两个操作数该操作符号 进行运算

#include <vector>
#include <string>
#include <stack>
#include <algorithm>
using namespace std;
class Solution {
private:
	stack<int> operandStack;
public:
	int evalRPN(vector<string>& tokens) {
		for (int i = 0; i < tokens.size(); i++)
			if (isSymbol(tokens[i])) {
				int a = operandStack.top();
				operandStack.pop();
				int b = operandStack.top();
				operandStack.pop();
				operandStack.push(operateNums(b, a, tokens[i]));
			}
			else
				operandStack.push(stoi(tokens[i]));
		return operandStack.top();
	}
private:
	bool isSymbol(const string &str) {
		if (str == "+" || str == "-" || str == "*" || str == "/")
			return true;
		else
			return false;
	}
	int operateNums(const int& a, const int &b, string operatorStr) {
		int sum = 0;
		if (operatorStr == "+")
			sum = a + b;
		else if (operatorStr == "-")
			sum = a - b;
		else if (operatorStr == "*")
			sum = a * b;
		else if (operatorStr == "/")
			sum = a / b;
		return sum;
	}
};

拓展:

https://www.cnblogs.com/chensongxian/p/7059802.html
此博客详细讲解了前缀、中缀、后缀,以及中缀转前缀中缀转后缀


中缀转前缀 与 中缀转后缀:

使用两个栈,分别维护操作符和数字,来进行 中缀 转 前缀or后缀

1、中缀转前缀:
(1)初始化两个栈:运算符 栈s1储存中间结果(操作数)的 栈s2
(2)从左←←←右扫描中缀表达式
(3)遇到操作数时,将其压入s2
(4)遇到运算符时,比较其与s1栈顶运算符的优先级
--------如果s1为空,或栈顶运算符为右括号 “)”,则直接将此运算符入s1
--------否则,若优先级比栈顶运算符的较高或相等,也将运算符压入s1
--------否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4)s1中新的栈顶运算符相比较
(5)遇到括号时
--------如果是右括号 “)”,则直接压入s1
--------如果是左括号 “(”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到右括号“)” 为止,此时将这一对括号丢弃
(6)重复步骤2→→5,直到表达式的最左边
(7)将s1中剩余的运算符依次弹出并压入s2
(8)依次弹出s2中的元素并输出,结果即为中缀表达式对应的前缀表达式

2、中缀转后缀:
(1)初始化两个栈:运算符 栈s1,储存中间结果(操作数)的 栈s2
(2)从左→→→右扫描中缀表达式
(3)遇到操作数时,将其压s2
(4)遇到运算符时,比较其与s1栈顶运算符的优先级:
--------如果s1为空,或栈顶运算符为左括号 “(”,则直接将此运算符入s1
--------否则,若优先级比栈顶运算符的高,也将运算符压入s1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况)
--------否则,将s1栈顶的运算符弹出并压入到s2中,再次转到(4)s1中新的栈顶运算符相比较
(5)遇到括号时:
--------如果是左括号 “(”,则直接压入s1
--------如果是右括号 “)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到 左括号"(" 为止,此时将这一对括号丢弃
(6)重复步骤 2→→5,直到表达式的最右边
(7)将s1中剩余的运算符依次弹出并压入s2
(8)依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值