4.4.5 中缀表达式转后缀表达式(逆波兰计算器)

具体步骤

  • 1)初始化两个栈: 运算符栈s1和存储中间结果的栈s2

  • 2)从左至右扫描中缀表达式

  • 3)遇到操作数时,将其压入s2

  • 4)遇到运算符时,比较其与s1栈顶运算符的优先级:

    • (1)如果s1为null,或栈顶运算符为左括号”(“,则直接将此运算符入栈
    • (2)否则,若优先级比栈顶运算符的高,也将运算符压入s1
    • (3)否则,将s1栈顶的运算符弹出并压入到s2中,再次转到 (4-1)中与s1中新的栈顶运算符想比较
  • 5)遇到括号的

    • (1)如果是左括号”(“ ,则直接压入s1
    • (2)如果是右括号”)“,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
  • 6)重复步骤2-5,直到表达式的最右边

  • 7)将s1中剩余的运算符依次弹出并压入s2

  • 8)依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式

package com.ldm.stack;import java.util.ArrayList;
import java.util.List;
import java.util.Stack;/*** @author 梁东明* 2022/8/24* 86139* 点击setting在Editor 的File and Code Templates 修改*/
@SuppressWarnings({"all"})
public class PolandNotation {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> list = getMiddleExpressionListString(expression);System.out.println("中缀表达式= " + list);List<String> parseSuffixExpressionList = parseSuffixExpressionList(list);System.out.println("后缀表达式 = " + parseSuffixExpressionList);int res = calculator(parseSuffixExpressionList);System.out.println("最后的计算结果是 = " + res);/*先定义给逆波兰表达式//(30+4)×5-6  => 30 4 + 5 × 6 - => 164// 4 * 5 - 8 + 60 + 8 / 2 => 4 5 * 8 - 60 + 8 2 / +//测试//说明为了方便,逆波兰表达式 的数字和符号使用空格隔开//String suffixExpression = "3 4 + 5 * 6 -"  ==29;//String suffixExpression = "4 5 * 8 - 60 + 8 2 / +"; // 76//思路//1. 先将 "3 4 + 5 × 6 - " => 放到ArrayList中//2. 将 ArrayList 传递给一个方法,遍历 ArrayList 配合栈 完成计算String suffixExpression = "30 4 + 5 * 6 -";List<String> list = getListString(suffixExpression);System.out.println("rpnList=" + list);int res = calculator(list);System.out.println("res = " + res);*/}//3. 将得到的中缀表达式对应的List => 后缀表达式对应的List//   即 ArrayList [1,+,(,(,2,+,3,),*,4,),-,5]  =》 ArrayList [1,2,3,+,4,*,+,5,–]public static List<String> parseSuffixExpressionList(List<String> ls){//定义两个栈 符号栈s1 和存放中间结果的栈s2Stack<String> s1 = new Stack<>();//说明:因为s2 这个栈,在整个转换过程中,没有pop操作,而且后面我们还需要逆序输出//因此比较麻烦,这里我们就不用 Stack<String> 直接使用 List<String> s2//Stack<String> s2 = new Stack<String>(); // 储存中间结果的栈s2List<String> s2 = new ArrayList<String>(); // 储存中间结果的Lists2//遍历传入的lsfor (String item : ls) {//如果是一个数,就加入s2中,要使用正则表达式,开启多位数的识别if (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中新的栈顶运算符相比较//编写一个Operate类,再编写getValue方法来获取当前运算符的优先级while (s1.size() != 0 && Operation.getValue(s1.peek()) >=Operation.getValue(item)){//把s1中的运算符加入s2,直到,item的优先级大于s1栈顶的运算符,退出循环,并且将item压入s1s2.add(s1.pop());}//还需要将item压入栈s1.push(item);}}//将s1中剩余的运算符依次弹出并加入s2while(s1.size() != 0) {s2.add(s1.pop());}return s2; //注意因为是存放到List, 因此按顺序输出就是对应的后缀表达式对应的List}//将中缀表达式转换成对应的list// s 对应的是中缀表达式expressionpublic static List<String > getMiddleExpressionListString(String s){//定义一个List,存放中缀表达式 对应的内容List<String> ls = new ArrayList<>();int i = 0; //这时是一个指针,用于遍历 中缀表达式字符串String str; // 对多位数的拼接char c; // 每遍历到一个字符,就放入到cdo {//为什么是47  58 你要去问编写ASCII码的那群家伙。//47对应的是0 58对应的是9,不信的可以去百度查一下//如果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中public static List<String > getListString(String suffixExpression){//将表达式分割String[] s = suffixExpression.split(" ");List<String> list = new ArrayList<>();for (String  data : s) {list.add(data);}return list;}//完成对逆波兰表达式的运算/** 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 calculator(List<String> ls){//创建栈,只需要一个栈即可Stack<String> stack = new Stack<>();//遍历 lsfor (String item : ls) {//使用正则表达式取出数来if ( item.matches("\\d+")){ //匹配的是多位数//入栈stack.push(item);}else {//pop出两个数,并运算,在入栈int num1 = Integer.parseInt(stack.pop());int num2 = Integer.parseInt(stack.pop());int res = 0;if (item.equals("+")){res = num1 + num2;}else if (item.equals("-")){res = num2 - num1;}else if (item.equals("*")){res = num1 * num2;}else  if (item.equals("/")){res = num2 / num2 ;}else {throw new RuntimeException("没有这种运算符");}//把res入栈stack.push(""+ res  );}}//最后留在栈中的值就是运算得到的值return Integer.parseInt(stack.pop());}
}//编写一个类 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;}}

//本次逆波兰计算器出自韩顺平的 数据结构和算法教程,哔哩哔哩详细教程
在 36-42p,视频共有六个,大约在两小时左右。二倍速一个小时即可看完。

最后,认识一下,我是小白。努力成为一名合格的程序员。期待与你的下次相遇。

中缀表达式转后缀表达式(Java)相关推荐

  1. java中缀表达式转后缀表达式(逆波兰算法)

    四则运算是栈的重要应用之一 中缀表达式转后缀表达式(逆波兰算法)过程 从左到右遍历中缀表达式 数字直接输出为后缀表达式一部分 如果是符号,则判断与栈顶元素的优先级 高于栈顶元素优先级直接入栈 低于或等 ...

  2. java中缀表达式转后缀表达式_数据结构Java实现06----中缀表达式转换为后缀表达式...

    本文主要内容: 表达式的三种形式 中缀表达式与后缀表达式转换算法 一.表达式的三种形式: 中缀表达式:运算符放在两个运算对象中间,如:(2+1)*3.我们从小做数学题时,一直使用的就是中缀表达式. 后 ...

  3. 数据结构中缀表达式转后缀表达式与后缀表达式的求值实训报告_动图+源码,演示 Java 中常用数据结构执行过程及原理...

    程序员的成长之路互联网/程序员/成长/职场 关注 阅读本文大概需要 3.7 分钟. 作者:大道方圆cnblogs.com/xdecode/p/9321848.html 最近在整理数据结构方面的知识, ...

  4. Java数据结构之中缀表达式转后缀表达式

    简介 通过数组模拟栈进行中缀表达式转后缀表达式,再进行计算 不说废话,请看代码. package com.atguigu.Stack;import java.util.ArrayList; impor ...

  5. Java中缀表达式转后缀表达式.

    有点不好写,大家可以看看这个思路,当然有多种方法! package zhan;import java.util.ArrayList; import java.util.List; import jav ...

  6. java利用栈求复杂表达式_java中的栈Stack的基本使用和应用(二) ——利用栈计算合法的算术表达,中缀表达式转后缀表达式...

    利用栈Stack计算合法的算术表达式 限定的算术表达式求值问题:包含 "+"."-"."*"."/" .正整数和圆括号的 ...

  7. 逆波兰式 java_逆波兰式(后缀表达式)的计算 中缀表达式转后缀表达式(逆波兰式)【java实现】...

    一.逆波兰式(后缀表达式)计算 思路: * 1.遍历逆波兰式的集合 * 2.当遍历的元素为数字时,入栈 stack * 3.当遍历的元素为运算符时,stack栈弹出两个数,num2 num1,并用该运 ...

  8. 九、中缀表达式转为后缀表达式

    使用栈将中缀表达式转为后缀表达式并计算 一.中缀表达式转换为后缀表达式 由于后缀表达式适合计算式进行计算,但是人对于较长的中缀表达式,很难将中缀表达式直接转换为后缀表达式,于是我们使用栈来实现中缀表达 ...

  9. 前缀、中缀和后缀表达式详解,中缀表达式到后缀表达式的转换规则,以及后缀表达式的计算规则,附计算代码

    1. 中缀.前缀和后缀表达式 1.1 中缀表达式 首先,中缀表达式的这个"缀"指运算符在两个操作数的位置.中缀表达式其实就是我们常用的算术表达式,比如 2 + 9 - (32 * ...

  10. Java堆栈的应用2----------中缀表达式转为后缀表达式的计算Java实现

    1.堆栈-Stack 堆栈(也简称作栈)是一种特殊的线性表,堆栈的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置进行插入和删除操作,而堆栈只允许在固定一端进行插入和删除 ...

最新文章

  1. 线粒体|GetOrganelle组装软件
  2. html进度条圆圈渐变色,HTML5 canvas带渐变色的圆形进度条动画
  3. Android socket 编程 实现消息推送(二)
  4. python【蓝桥杯vip练习题库】ALGO-82 输出米字形
  5. 自动开料机器人_工业4.0智能家具无人化生产线 自动化无人化大势所趋
  6. ISE调用Notepad++并且实现错误高亮定位的方法
  7. CUDA 编程实例:计算点云法线
  8. ado.net操作数据库
  9. Python运算符优先级
  10. 学习OpenVINO笔记之Inference Engine
  11. python的django_真正搞明白Python中Django和Flask框架的区别
  12. 如何更好利用大数据的优势
  13. 让APP不被android系统杀掉
  14. 浙江大学计算机系自主招生题目,浙江大学自主招生试题
  15. Jvav常问面试题(附解析)
  16. Udesk即时通讯网页插件发送咨询对象(一、使用内嵌代码)
  17. Web of science以及中国知网学术论文爬取教程(附代码)
  18. 【每日一题】89. 格雷编码
  19. 机器学习中的L1和L2正则化项
  20. 什么是元数据管理?以及该如何做元数据管理呢?

热门文章

  1. IE、FF CSS 兼容性、兼容浏览器的技巧 2
  2. 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
  3. 【保证能用】Ubuntu创建一个正常权限的用户
  4. ARM与x86–蝶变ARM
  5. CompletableFuture异步任务的简单使用
  6. 七个常见队列的简单学习
  7. Linux服务跟随启动,关于linux服务启动与自启动
  8. python 奥数_Python 和 奥数 — 同余法求数值
  9. spring-kafka广播模式配置_交换机为什么要划分vlan?交换机如何配置
  10. Java接口和抽象类区别