目录

  • 关于中缀与后缀表达式
  • 中缀转后缀表达
  • 后缀表达的计算
  • 程序实现

今天是很闷热的一天,还是坚持着学完既定课程并做好总结

关于中缀与后缀表达式

所述的 中缀表达式就是人们平时所看到的数学表达式形式,以人们易读的形式展现(数字之间夹杂着运算符)并且要考虑括号的优先计算。

这样的表达式其实是不利于计算机计算的,关于中缀表达式的计算机计算实现可以看我上一篇博客

伟大的计算机学者发明出一种后缀表达式,使计算机更容易计算数学式子,我们需要做的有两部分,第一部分是中缀转后缀表达,第二部分是后缀表达的计算

中缀转后缀表达

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

举例一个中缀表达

1+((2+3)*4)-5

其转换为后缀的过程如下图所示

实际上这里并不需要两个栈结构,因为s2从始至终未执行pop出栈操作,且最后要对s2进行逆序排列,因此最方便的数据结构是使用list,顺序add顺序输出即可。

后缀表达的计算

从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
例如后缀表达式“1 2 3 + 4 * + 5 -”:
(1) 从左至右扫描,将1和2和3压入堆栈;
(2) 遇到+运算符,因此弹出3和2(3为栈顶元素,2为次顶元素,注意与前缀表达式做比较),计算出3+2的值,得5,再将5入栈;
(3) 将4入栈;
(4) 接下来是×运算符,因此弹出4和5,计算出4×5=20,将20入栈;
(5) 接下来是+运算符,弹出20和1,计算20+1=21,将21入栈;
(6) 将5入栈;
(6) 最后是-运算符,计算出21-5的值,即16,由此得出最终结果。

程序实现

package com.tunan.stack;import java.util.ArrayList;
import java.util.List;
import java.util.Stack;public class PolandNotation {public static void main(String[] args) {//完成将中缀表达式转后缀表达式的操作String expression = "1+((2+3)*4)-5";List<String> infixExpressionList = toInfixExpressionList(expression);System.out.println(infixExpressionList);List<String> parseSuffixExpressionList = parseSuffixExpressionList(infixExpressionList);System.out.println(parseSuffixExpressionList);System.out.printf("expression %s = %d \n", expression, calculate(parseSuffixExpressionList));}//中缀list转后缀listpublic static List<String> parseSuffixExpressionList(List<String> ls){//定义两个栈Stack<String> s1 = new Stack<String>();//符号栈//储存中间结果的栈  不必是栈结构,可以用list,因为没有出栈操作//Stack<String> s2 = new Stack<String>();List<String> s2 = new ArrayList<String>();//遍历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();//将左括号也弹出哦!!从而消除括号} else{//当item的优先级小于等于s1栈顶符号时,将s1栈顶运算符弹出加入到s2,再次比较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;//s2 是list 因此按顺序输出即可,不需要像栈一样再进行倒序操作}//将中缀转成listpublic static List<String> toInfixExpressionList(String s) {List<String> ls = new ArrayList<String>();int i = 0;//指针,用于遍历sString str;//对多位数的拼接char c;//遍历到的字符放入c中do {//如果c不是一个非数字if((c = s.charAt(i)) < 48 ||(c = s.charAt(i)) > 57){ls.add("" + c);i++;}else {//是数字就需要考虑多位数的拼接str = "";//str置成空串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) {//将suffixExpression分割String[] split = suffixExpression.split(" ");List<String> list = new ArrayList<String>();for(String ele: split){list.add(ele);}return list;}//完成逆波兰表达式的计算/*遇到 + 运算符,弹出4和3(4是栈顶元素,3是次栈顶元素),计算出3+4得7,将7入栈将5入栈下面遇到*运算符,因此弹出5和7,计算7*5得35,将35入栈将6入栈最后遇到 - 运算符,计算35-6,得最终结果*/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;switch (item) {case "+":res = num1 + num2;break;case "-":res = num1 - num2;break;case "*":res = num1 * num2;break;case "/":res = num1 / num2;break;default:break;}stack.push(res + "");//int转string}}//最后留在stack中的数是结果return Integer.parseInt(stack.pop());}}//编写一个返回运算符对应优先级的类
class Operation{private static int ADD = 1;private static int SUB = 1;private static int MUL = 2;private static int DIV = 3;public static int getValue(String operation){int res = 0;switch (operation) {case "+":res = ADD;break;case "-":res = SUB;break;case "*":res = MUL;break;case "/":res = DIV;break;default:System.out.println("运算符出错");break;}return res;}
}

程序结果是:

数据结构(八)——后缀表达式相关推荐

  1. java求值不用后缀表达式_数据结构之后缀表达式求值(java实现)

    数据结构之后缀表达式求值(java实现) 前记 ​ 今天在刷leet code的时候刷到了一道题,后缀表达式(逆波兰表达式)求值,我花了一会儿写了一下它的解法.但是今天我不谈什么是后缀表达式,有兴趣的 ...

  2. python前缀表达式求值_python数据结构与算法 11 后缀表达式求值

    从本节开始,删除原版的英文,直接发译后的文稿. 后缀表达式求值 栈的最一个应用例子,计算一个后缀表达式的值.这个例子中仍然用栈的数据结构.不过,当扫描表达式的时候,这次是操作数压栈等待,不是转换算法中 ...

  3. Java数据结构和算法(六)——前缀、中缀、后缀表达式

    前面我们介绍了三种数据结构,第一种数组主要用作数据存储,但是后面的两种栈和队列我们说主要作为程序功能实现的辅助工具,其中在介绍栈时我们知道栈可以用来做单词逆序,匹配关键字符等等,那它还有别的什么功能吗 ...

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

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

  5. 数据结构-栈应用之逆波兰表达式(后缀表达式)

    逆波兰表达式含义我就不做赘述了,摘自百科上的一段话: 逆波兰表达式又叫做后缀表达式.在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表示.波兰逻辑学家J.Lukas ...

  6. 《数据结构》:中缀表达式转后缀表达式 后缀表达式的计算

    目录 一.基本概念 二.中缀表达式转后缀表达式 例       中缀表达式  2*(3+5)+7/1-4  转换为后缀表达式 三.后缀表达式的计算 例       后缀表达式  2 3 5 + * 7 ...

  7. 【数据结构与算法篇】什么是后缀表达式?

    什么是后缀.前缀.以及中缀表达式呢?他与我们平时在数学中见到的表达式有什么区别?第一次看这个名词,我还是有点蒙,难理解,所以做以下笔记,以便日后复习,也希望可以帮助读者,以相互促进. 文章目录 前言: ...

  8. 有趣的数据结构算法10——后缀表达式(PRN)介绍及利用栈计算后缀表达式的结果

    有趣的数据结构算法10--后缀表达式(PRN)介绍及利用栈计算后缀表达式的结果 解题思路 实现代码 GITHUB下载连接 在前一天已经利用栈完成2进制到8进制的转换.但是栈的应用方面还有很多,本次我将 ...

  9. 【数据结构与算法】【12】前缀表达式、中缀表达式、后缀表达式

    什么是前缀表达式.中缀表达式.后缀表达式 前缀表达式.中缀表达式.后缀表达式,是通过树来存储和计算表达式的三种不同方式 以如下公式为例 (a+(b−c))∗d( a+(b-c) )*d(a+(b−c) ...

最新文章

  1. Go 知识点(19)— Go 语言中的野指针
  2. 简单剖析智能指针的思想
  3. Ubuntu 16.04 下修改免安裝版tomcat的內存大小
  4. 每日源码分析 - Lodash(remove.js)
  5. 构建一个自定义CentOS7内核
  6. 计算机专业Top20,全国计算机软件专业大学排名TOP20,清华居然不是第一!
  7. 我的成长笔记20210330(测试空闲期)
  8. 大学生 生活小技巧:利用插件(Tampermonkey )学习网课 | 查题
  9. Unity插件——Odin 学习笔记(三)
  10. c语言实例 魔术师的猜牌术(1),C语言猜牌术代码解析
  11. 《多收了三五斗》大学毕业版 (转)
  12. 登录mysql报错Failed to connect to backoff 或 Failed to get D-Bus connection: Operation not permitted解决方法
  13. 已解决:GET http://localhost:8080/statics/js/jquery-3.4.1.js net::ERR_ABORTED 404
  14. 初学者LDPC码扫盲
  15. 微生物共现网络可视化:实现布局自由
  16. 计算机曲谱卡农,卡农曲谱.doc
  17. [转载]45岁以后,外企的人都到去哪里了
  18. ROS采集GPS/北斗数据在百度地图中可视化位置
  19. 计算机的符号名称大全集,所有电脑特殊符号 大合集 !
  20. 最近开发了一个款安卓手机应用【摇摇语音记事本】

热门文章

  1. SAP PS常用事务代码T-CODE
  2. Python—遇到的问题,使用PyPDF2转化pdf时候遇到的各种问题。
  3. 针对Android设备的开源手机银行木马BankBot / Mazain分析
  4. Redis(三)【五大数据类型三种特殊数据类型】
  5. Show一下拿的奖杯
  6. 音频和视频标签 与其他标签
  7. R语言运行环境安装配置
  8. 关于CClientDC与CPAINTDC,以及GetDC与GetWindowDC。
  9. Fresco高斯模糊使用
  10. 2021年美容师(高级)考试资料及美容师(高级)考试技巧