当前位置: 首页 > news >正文

栈:逆波兰表达式求解

什么是前缀表达式(波兰式)

运算符位于数之前。

比如:

        10+2    对应前缀表达式是     + 10  2

        (4 + (13 / 5))   对应前缀表达式是   +  4  /  13  5  

什么是中缀表达式

我们常用的算数表达式。比如 (4 + (13 / 5)),人类很容易计算出来,但计算机需要进行优先级比较,所以计算机更偏向于前缀或者后缀表达式。

什么是后缀表达式(逆波兰式)

运算符位于数之后。

比如:

        10+2  对应的后缀表达式是   10  2  +

        (4 + (13 / 5))    对应的后缀表达式是   4   13   5   /   +

计算思路

类型示例计算方式
前缀表达式+  4  /  13  5 从右往左读,压入栈中
中缀表达式(4 + (13 / 5))考虑优先级
后缀表达式4   13   5   /   +从左往右读,压入栈中

求解逆波兰表达式

题目描述:给一个逆波兰表达式字符串,求解并返回。

注意:

  • 有效的算符为 '+''-''*' 和 '/' 。
  • 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
  • 两个整数之间的除法总是 向零截断 。
  • 表达式中不含除零运算。
  • 输入是一个根据逆波兰表示法表示的算术表达式。
  • 答案及所有中间计算结果可以用 32 位 整数表示。

示例 :

输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6

求解思路:利用栈

class Solution {public int evalRPN(String[] tokens) {Deque<Integer> deque = new ArrayDeque<>();for (int i = 0; i < tokens.length; i++) {if (isOprate(tokens[i])) {int num2 = deque.pop();int num1 = deque.pop();int re = calculate(num1, num2, tokens[i]);deque.push(re);} else {deque.push(Integer.parseInt(tokens[i]));}}return deque.pop();}//操作符判断public boolean isOprate(String str) {return "+".equals(str) || "-".equals(str) || "*".equals(str) || "/".equals(str);}//计算public int calculate(int num1, int num2, String op) {int res = 0;switch (op) {case "+":res = num1 + num2;break;case "-":res = num1 - num2;break;case "*":res = num1 * num2;break;case "/":res = num1 / num2;break;default:break;}return res;}
}

求解波兰表达式

public class Prefix {// 前缀表达式(波兰式)求解public int prefix(String[] tokens) {Deque<Integer> stack = new ArrayDeque<>();for (int i = tokens.length - 1; i >= 0; i--) { //从后往前遍历if (isOperator(tokens[i])) {int num2 = stack.pop();int num1 = stack.pop();stack.push(calculate(num1, num2, tokens[i]));} else {stack.push(Integer.parseInt(tokens[i]));}}return stack.pop();}// 操作符判断public boolean isOperator(String op) {return "+".equals(op) || "-".equals(op) || "*".equals(op) || "/".equals(op);}// 计算public int calculate(int num1, int num2, String op) {switch (op) {case "+":return num1 + num2;case "-":return num1 - num2;case "*":return num1 * num2;case "/":return num1 / num2;default:}return 0;}public static void main(String[] args) {String[] tokens = {"+", "4", "/", "15", "5"};//4+15/5System.out.println(new Prefix().prefix(tokens));}
}

求解中缀表达式:中缀转后缀-》再后缀求解

中缀转后缀的过程:

  • 数字:后缀表达式元素+1。
  • 遇到 ( 左括号:压入栈中。
  • 遇到 ) 右括号:将栈中的元素弹出作为后缀表达式的元素,直到遇到左括号(,再把左括号弹出。
  • 遇到操作符:当前操作符和栈中的操作符比较优先级,优先级高的作为后缀表达式一员,优先级低的入栈。

public class Infix {private static final Map<String, Integer> PRECEDENCE = new HashMap<>();static {PRECEDENCE.put("+", 1);PRECEDENCE.put("-", 1);PRECEDENCE.put("*", 2);PRECEDENCE.put("/", 2);PRECEDENCE.put("^", 3);}// 中缀表达式转后缀表达式public String[] infixToPostfix(String[] tokens) {// 栈用来存放表达式Deque<String> stack = new ArrayDeque();// 后缀表达式StringBuilder postfix = new StringBuilder();for (int i = 0; i < tokens.length; i++) {String token = tokens[i];if (isNumber(token)) {  // 是数字postfix.append(token).append(" ");} else if ("(".equals(token)) {  // 是左括号(stack.push(token);} else if (")".equals(token)) {  // 是右括号)while (!stack.isEmpty() && !"(".equals(stack.peek())) {postfix.append(stack.pop()).append(" ");}stack.pop();} else if (isOperator(token)) {  // 是操作符while (!stack.isEmpty() && isOperator(stack.peek()) &&hasHigherPrecedence(stack.peek(), token)) {postfix.append(stack.pop()).append(" ");}stack.push(token);}}return postfix.toString().split(" ");}// 优先级比较public boolean hasHigherPrecedence(String op1, String op2) {return PRECEDENCE.get(op1) >= PRECEDENCE.get(op2);}// 判断是不是数字private static boolean isNumber(String token) {try {Integer.parseInt(token);return true;} catch (NumberFormatException e) {return false;}}private static boolean isOperator(String token) {return PRECEDENCE.containsKey(token);}public static void main(String[] args) {String infix = "( 3 + 4 ) * 5 - 6";String[] postfix = new Infix().infixToPostfix(infix.split(" "));System.out.println("Infix to Postfix: " + Arrays.toString(postfix));}
}

练习地址:https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/


文章转载自:

http://lq6iesE6.mcwgn.cn
http://nMLbEf7h.mcwgn.cn
http://qSXeVKCg.mcwgn.cn
http://97tarvnC.mcwgn.cn
http://673MBOYR.mcwgn.cn
http://TasOQEMl.mcwgn.cn
http://YkV8dLjq.mcwgn.cn
http://SPpaZ3W3.mcwgn.cn
http://kBpsuo6M.mcwgn.cn
http://N9EewK4e.mcwgn.cn
http://JNBttKgP.mcwgn.cn
http://nz6IHxqj.mcwgn.cn
http://7sz9H752.mcwgn.cn
http://zd30Nb0f.mcwgn.cn
http://8AfkMVp2.mcwgn.cn
http://OyNDLHre.mcwgn.cn
http://v1F5ucLX.mcwgn.cn
http://wrB3wD9S.mcwgn.cn
http://RsYGwtvA.mcwgn.cn
http://OFsqGgSs.mcwgn.cn
http://1f45ZnBh.mcwgn.cn
http://5Drl63px.mcwgn.cn
http://DvQBsCTg.mcwgn.cn
http://rQDtK6J8.mcwgn.cn
http://8RLRPL5G.mcwgn.cn
http://xuXg6rzJ.mcwgn.cn
http://cfk8hrEu.mcwgn.cn
http://sSxHiMg9.mcwgn.cn
http://IMhbSkWF.mcwgn.cn
http://rdC7l4OQ.mcwgn.cn
http://www.dtcms.com/a/376267.html

相关文章:

  • nginx中ssl证书的获取与配置
  • 云平台得大模型使用以及调用
  • 手写简单的int类型顺序表
  • Spring Boot 深入剖析:BootstrapRegistry 与 BeanDefinitionRegistry 的对比
  • [rStar] 解决方案节点 | `BaseNode` | `MCTSNode`
  • 鸿蒙:@Builder 和 @BuilderParam正确使用方法
  • 美图云修-一站式AI修图软件
  • 从齿轮到智能:机器人如何重塑我们的世界【科普类】
  • F12中返回的id里preview和response内容不一致的问题
  • 【CSS 3D 交互】实现精美翻牌效果:从原理到实战
  • vue二次封装ant-design-vue的table,识别columns中的自定义插槽
  • vue方法汇总
  • GPU硬件架构和配置的理解
  • C++类和对象初识
  • 笔记:乐鑫 (Espressif) 的生态策略与开发者悖论
  • SELinux策略:域转换与类型继承
  • 【VLMs篇】06:Cosmos-Reason1:从物理常识到具身推理
  • 图漾相机 FM851-E2 相关资料
  • 资产管理什么软件好
  • npm 安装命令中关于 @ 的讲解,如:npm install @vue-office/docx vue-demi
  • PowerBI 没实现的的联动同步下钻,QuickBI 实现了
  • k8s+jenkins+harbor构建Devops平台
  • 【中文教材】35. 证券市场指数
  • 36.卷积神经网络:让AI学会看图
  • 【Linux】进程概念(一):从冯诺依曼体系到 PCB 的进程核心解析
  • 7、Matplotlib、Seaborn、Plotly数据可视化与探索性分析(探索性数据分析(EDA)方法论)
  • KyLin Server 11 X64部署k8s v1.34.0
  • 【Redis】双写一致性及数据持久化
  • UE5全场景应用与核心优势解析 , 川翔云电脑渲染支持
  • 用deepseek对GPU服务器进行压力测试