前缀中缀后缀表达式的计算求值

原文在这里

表达式

前缀表达式(波兰表达式)

  1. 前缀表达式又称波兰式,前缀表达式的运算符位于操作数之前
  2. 举例说明: (3+4)×5-6 对应的前缀表达式就是 - × + 3 4 5 6

前缀表达式求值

前缀表达式的计算机求值

从右至左扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(栈顶元素 和 次顶元素),并将结果入栈;重复上述过程直到表达式最左端,最后运算得出的值即为表达式的结果

例如: (3+4)×5-6 对应的前缀表达式就是 - × + 3 4 5 6 , 针对前缀表达式求值步骤如下:

  • 从右至左扫描,将6、5、4、3压入堆栈
  • 遇到+运算符,因此弹出34(3为栈顶元素,4为次顶元素),计算出3+4的值,得7,再将7入栈
  • 接下来是×运算符,因此弹出75,计算出7×5=35,将35入栈
  • 最后是-运算符,计算出35-6的值,即29,由此得出最终结果

中缀表达式

中缀表达式

中缀表达式就是常见的运算表达式,如(3+4)×5-6

中缀表达式的求值是我们人最熟悉的,但是对计算机来说却不好操作(前面我们讲的案例就能看的这个问题),因此,在计算结果时,往往会将中缀表达式转成其它表达式来操作(一般转成后缀表达式.)

中缀表达式对于我们人来好搞,计算机他算不算明白,就离谱

计算机不知道怎么算这个优先级

后缀表达式(逆波兰表达式)

后缀表达式

后缀表达式又称逆波兰表达式,与前缀表达式相似,只是运算符位于操作数之后

中举例说明: (3+4)×5-6 对应的后缀表达式就是 3 4 + 5 × 6 –

再比如:

正常的表达式逆波兰表达式
a+ba b +
a+(b-c)a b c - +
a+(b-c)*da b c – d * +
a+d*(b-c)a d b c - * +
a=1+3a 1 3 + =

后缀表达式的计算机求值

从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 和 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果

例如: (3+4)×5-6 对应的后缀表达式就是 3 4 + 5 × 6 - , 针对后缀表达式求值步骤如下:

  1. 从左至右扫描,将3和4压入堆栈;
  2. 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈;
  3. 将5入栈;
  4. 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
  5. 将6入栈;
  6. 最后是-运算符,计算出35-6的值,即29,由此得出最终结果

我们完成一个逆波兰计算器,要求完成如下任务:

  1. 输入一个逆波兰表达式(后缀表达式),使用栈(Stack), 计算其结果
  2. 支持小括号和多位数整数,因为这里我们主要讲的是数据结构,因此计算器进行简化,只支持对整数的计算。
  3. 思路分析
  4. 代码完成
package com.atguigu.stack;/*** ClassName:  <br/>* Description:  <br/>* Date: 2021-02-20 14:27 <br/>* @project data_algorithm* @package com.atguigu.stack*/import java.util.ArrayList;
import java.util.List;
import java.util.Stack;public class PolandNotation {}
//编写一个类 Operation 可以返回一个运算符 对应的优先级
class Operation {private static int ADD = 1;private static int SUB = 1;private static int MUL = 2;private static int DIV = 2;//写一个方法,返回对应的优先级数字public static int getValue(String operation) {int result = 0;switch (operation) {case "+":result = ADD;break;case "-":result = SUB;break;case "*":result = MUL;break;case "/":result = DIV;break;default:System.out.println("不存在该运算符" + operation);break;}return result;}}
//完成对逆波兰表达式的运算
/** 1)从左至右扫描,将3和4压入堆栈;2)遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈;3)将5入栈;4)接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;5)将6入栈;6)最后是-运算符,计算出35-6的值,即29,由此得出最终结果*/public static int calculate(List<String> ls) {// 创建给栈, 只需要一个栈即可Stack<String> stack = new Stack<String>();// 遍历 lsfor (String item : ls) {// 这里使用正则表达式来取出数if (item.matches("\\d+")) { // 匹配的是多位数// 入栈stack.push(item);} else {// pop出两个数,并运算, 再入栈int num2 = Integer.parseInt(stack.pop());int num1 = Integer.parseInt(stack.pop());int res = 0;if (item.equals("+")) {res = num1 + num2;} else if (item.equals("-")) {res = num1 - num2;} else if (item.equals("*")) {res = num1 * num2;} else if (item.equals("/")) {res = num1 / num2;} else {throw new RuntimeException("运算符有误");}//把res 入栈stack.push("" + res);}}//最后留在stack中的数据是运算结果return Integer.parseInt(stack.pop());
}
//将一个逆波兰表达式, 依次将数据和运算符 放入到 ArrayList中
public static List<String> getListString(String suffixExpression) {//将 suffixExpression 分割String[] split = suffixExpression.split(" ");List<String> list = new ArrayList<String>();for(String ele: split) {list.add(ele);}return list;}
//方法:将 中缀表达式转成对应的List
//  s="1+((2+3)×4)-5";
public static List<String> toInfixExpressionList(String s) {//定义一个List,存放中缀表达式 对应的内容List<String> ls = new ArrayList<String>();int i = 0; //这时是一个指针,用于遍历 中缀表达式字符串String str; // 对多位数的拼接char c; // 每遍历到一个字符,就放入到cdo {//如果c是一个非数字,我需要加入到lsif((c=s.charAt(i)) < 48 ||  (c=s.charAt(i)) > 57) {ls.add("" + c);i++; //i需要后移} else { //如果是一个数,需要考虑多位数str = ""; //先将str 置成"" '0'[48]->'9'[57]while(i < s.length() && (c=s.charAt(i)) >= 48 && (c=s.charAt(i)) <= 57) {str += c;//拼接i++;}ls.add(str);}}while(i < s.length());return ls;//返回
}
//即 ArrayList [1,+,(,(,2,+,3,),*,4,),-,5]  =》 ArrayList [1,2,3,+,4,*,+,5,–]
//方法:将得到的中缀表达式对应的List => 后缀表达式对应的List
public static List<String> parseSuffixExpreesionList(List<String> ls) {//定义两个栈Stack<String> s1 = new Stack<String>(); // 符号栈//说明:因为s2 这个栈,在整个转换过程中,没有pop操作,而且后面我们还需要逆序输出//因此比较麻烦,这里我们就不用 Stack<String> 直接使用 List<String> s2//Stack<String> s2 = new Stack<String>(); // 储存中间结果的栈s2List<String> s2 = new ArrayList<String>(); // 储存中间结果的Lists2//遍历lsfor(String item: ls) {//如果是一个数,加入s2if(item.matches("\\d+")) {s2.add(item);} else if (item.equals("(")) {s1.push(item);} else if (item.equals(")")) {//如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃while(!s1.peek().equals("(")) {s2.add(s1.pop());}s1.pop();//!!! 将 ( 弹出 s1栈, 消除小括号} else {//当item的优先级小于等于s1栈顶运算符, 将s1栈顶的运算符弹出并加入到s2中,再次转到(4.1)与s1中新的栈顶运算符相比较//问题:我们缺少一个比较优先级高低的方法while(s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item) ) {s2.add(s1.pop());}//还需要将item压入栈s1.push(item);}}//将s1中剩余的运算符依次弹出并加入s2while(s1.size() != 0) {s2.add(s1.pop());}return s2; //注意因为是存放到List, 因此按顺序输出就是对应的后缀表达式对应的List}

执行

public static void main(String[] args) {//完成将一个中缀表达式转成后缀表达式的功能//说明//1. 1+((2+3)×4)-5 => 转成  1 2 3 + 4 × + 5 –//2. 因为直接对str 进行操作,不方便,因此 先将  "1+((2+3)×4)-5" =》 中缀的表达式对应的List//   即 "1+((2+3)×4)-5" => ArrayList [1,+,(,(,2,+,3,),*,4,),-,5]//3. 将得到的中缀表达式对应的List => 后缀表达式对应的List//   即 ArrayList [1,+,(,(,2,+,3,),*,4,),-,5]  =》 ArrayList [1,2,3,+,4,*,+,5,–]String expression = "1+((2+3)*4)-5";//注意表达式List<String> infixExpressionList = toInfixExpressionList(expression);System.out.println("中缀表达式对应的List=" + infixExpressionList); // ArrayList [1,+,(,(,2,+,3,),*,4,),-,5]List<String> suffixExpreesionList = parseSuffixExpreesionList(infixExpressionList);System.out.println("后缀表达式对应的List" + suffixExpreesionList); //ArrayList [1,2,3,+,4,*,+,5,–]System.out.printf("expression=%d", calculate(suffixExpreesionList)); // ?/*//先定义给逆波兰表达式//(30+4)×5-6  => 30 4 + 5 × 6 - => 164// 4 * 5 - 8 + 60 + 8 / 2 => 4 5 * 8 - 60 + 8 2 / +//测试//说明为了方便,逆波兰表达式 的数字和符号使用空格隔开//String suffixExpression = "30 4 + 5 * 6 -";String suffixExpression = "4 5 * 8 - 60 + 8 2 / +"; // 76//思路//1. 先将 "3 4 + 5 × 6 - " => 放到ArrayList中//2. 将 ArrayList 传递给一个方法,遍历 ArrayList 配合栈 完成计算List<String> list = getListString(suffixExpression);System.out.println("rpnList=" + list);int res = calculate(list);System.out.println("计算的结果是=" + res);*/
}

原文在这里

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/455087.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

psnr 计算

PSNR是“Peak Signal to Noise Ratio”的缩写&#xff0c;峰值信噪比。psnr一般是用于最大值信号和背景噪音之间的一个工程项目。 PSNR计算公式如下&#xff1a; 8bits表示法中&#xff0c;peak的最大值为255&#xff1b;MSE指Mean Square Error&#xff08;均方误差&#xff0…

光源时间_缩短背光源的使用寿命的原因

许多场所都会使用到led这种产品&#xff0c;这种产品经常用于背光的照亮中。但是由于使用led的局限性较大&#xff0c;所以led逐渐被背光源这种产品所代替&#xff0c;常常用于背景的照亮让宣传图可以展现出更好的视觉&#xff0c;这也是许多人选择背光源的原因。那么&#xff…

《结对-贪吃蛇-需求分析》

结对编程&#xff1a;贪吃蛇项目 准备阶段&#xff1a;安装Python、pygame 编写阶段&#xff1a;1. 设置游戏窗口 2. 设置游戏必要功能&#xff1a; a)开始、暂停、退出按钮 b)贪吃蛇身体 c)食物 d)移动贪吃蛇所需按键 3. 完善游戏&#xff1a;添加游戏时间、贪吃蛇失败次数…

视频中场的问题2009-04-03 19:38(一)

视频中场的问题2009-04-03 19:38(一) 场的用途&#xff1a; 让25帧/秒的电视画面帧速率&#xff0c;变为50帧/秒。使观众感受到更加流畅的画面。 (二) 场的由来&#xff1a; 在电视制作的时候&#xff0c;电视扫描一副画面的时间根据当地交流电源的频率来确定。比如中国交流电源…

递归应用场景和调用机制

原文链接:传送门 递归 迷宫问题(回溯) 概念 简单呐的说: 递归就是方法自己调用自己,每次调用时传入不同的变量,递归有助于编程者解决复杂的问题,同时让代码变得简洁. 案例-递归调用机制 打印问题 public static void test(int n){if(n>2){test(n-1);}System.out.print…

在vivado里用rtl描述_如何利用Vivado HLS处理许多位准确或任意精度数据类型

我们在设计硬件时&#xff0c;它往往是要求更精确的位宽。例如&#xff0c;一个filter的输入是12位和一个累加器的结果只需要一个最大范围为27位。然而对于硬件设计来说&#xff0c;使用标准的C数据类型会造成硬件成本的浪费。这就会造成我们要使用更多的LUT和寄存器&#xff0…

Spring4.0之四:Meta Annotation(元注解)

Spring框架自2.0开始添加注解的支持&#xff0c;之后的每个版本都增加了更多的注解支持。注解为依赖注入&#xff0c;AOP&#xff08;如事务&#xff09;提供了更强大和简便的方式。这也导致你要是用一个相同的注解到许多不同的类中去。这篇文章介绍meta annotation来解决这个问…

八皇后问题分析与Java实现

原文链接:传送门 八皇后问题 八皇后问题&#xff0c;是一个古老而著名的问题&#xff0c;是回溯算法的典型案例。该问题是国际西洋棋棋手马克斯贝瑟尔于1848年提出&#xff1a;在88格的国际象棋上摆放八个皇后&#xff0c;使其不能互相攻击&#xff0c;即&#xff1a;任意两个…

各种音视频编解码学习详解 h264 ,mpeg4 ,aac 等所有音视频格式

编解码学习笔记&#xff08;一&#xff09;&#xff1a;基本概念 媒体业务是网络的主要业务之间。尤其移动互联网业务的兴起&#xff0c;在运营商和应用开发商中&#xff0c;媒体业务份量极重&#xff0c;其中媒体的编解码服务涉及需求分析、应用开发、释放license收费等等。最…

shell 脚本比较字符串相等_shell脚本--逻辑判断与字符串比较

涉及到比较和判断的时候&#xff0c;要注意整数比较使用-lt&#xff0c;-gt&#xff0c;ge等比较运算符&#xff0c;详情参考&#xff1a;整数比较文件测试使用 -d, -f, -x等运算发&#xff0c;详情参考&#xff1a;文件测试逻辑判断使用 &&(且)、||(或)、&#xff…

单例模式之恶汉模式(详解)

一.设计模式 概念&#xff1a;设计模式是一套被反复使用、多人知晓的、经过分类编目的、代码设计经验的总结。 目的&#xff1a;是用设计模式可以重用代码&#xff0c;让代码更容易被他人理解&#xff0c;保证代码的可靠性。 二.为什么要使用单例模式&#xff1f; 如果创造出多…

JSP中的:request.getScheme()+://+request.getServerName()+:+request.getServer

String path request.getContextPath(); String basePath request.getScheme()"://"request.getServerName()":"request.getServerPort()path"/"; <base href" <%basePath%>"> 这个语句是用来拼装当前网页的相对…

迷宫回溯问题分析和实现

原文链接:传送门 迷宫问题 说明: 小球得到的路径&#xff0c;和程序员设置的找路策略有关即&#xff1a;找路的上下左右的顺序相关再得到小球路径时&#xff0c;可以先使用(下右上左)&#xff0c;再改成(上右下左)&#xff0c;看看路径是不是有变化测试回溯现象思考: 如何求出…

canvas clear 指定属性的元素_好程序员web前端分享CSS属性组成及作用

好程序员web前端分享CSS属性组成及作用学习目标1、css属性和属性值的定义2、css文本属性3、css列表属性4、css背景属性5、css边框属性6、css浮动属性一、css属性和属性值的定义属性&#xff1a;属性是指定选择符所具有的属性&#xff0c;它是css的核心&#xff0c;css2共有150多…

mybatis大于小于等于

大于&#xff1a;<![CDATA[>]]> 小于&#xff1a;<![CDATA[<]]> 等于&#xff1a;<![CDATA[]]> 大于等于&#xff1a;<![CDATA[>]]> 小于等于&#xff1a;<![CDATA[<]]>转载于:https://www.cnblogs.com/YuanFan123/p/7234530.html

2017年秋招-广联达面试及思考

面试官提问&#xff1a; 自我介绍&#xff08;没有做充分的准备&#xff0c;总感觉说的不好&#xff09;为什么选择做前端&#xff1f;在前端方向&#xff0c;你认为自身有哪些优点&#xff1f;前端需要掌握哪些技术知识点&#xff1f;看过哪些比较好的网站&#xff1f;会不会使…

排序算法介绍和分类

原文链接:传送门 排序算法的介绍 排序也成排序算法 排序也称排序算法(Sort Algorithm)&#xff0c;排序是将一组数据&#xff0c;依指定的顺序进行排列的过程。 排序的分类&#xff1a; 1) 内部排序: 指将需要处理的所有数据都加载到**内部存储器(内存)**中进行排序。 2) 外…

认识高清视频编码(MPEG、H.264、WMV-HD、RMVB)

文章出处&#xff1a;www.net1980.com 原创 最近两年&#xff0c;“高清”这个词语非常火热&#xff0c;已经成为家电和IT行业的最新潮流了。高清视频和普通视频有什么区别呢&#xff1f;主要是分辨率上的区别&#xff0c;720P视频的分辨率为1280X720&#xff0c;1080P视频的分…

解读SPP / SPPF / SimSPPF / ASPP / RFB / SPPCSPC

SPP与SPPF 一、SPP的应用的背景 在卷积神经网络中我们经常看到固定输入的设计&#xff0c;但是如果我们输入的不能是固定尺寸的该怎么办呢&#xff1f; 通常来说&#xff0c;我们有以下几种方法&#xff1a; &#xff08;1&#xff09;对输入进行resize操作&#xff0c;让他们…

go mongodb排序查询_《MongoDB》day two

Mongodb的更新方式有&#xff1f;db.集合名.update() 函数:用于更新已存在的文档。语法格式&#xff1a;db.COLLECTION_NAME.update({查询条件},{更新内容},{更新参数(可选)}) 注&#xff1a;这种方式会覆盖原有的文档。使用更新操作符 使用 save()函数更新文档 Mongodb的updat…