很久没有关注算法和数据结构,大部分知识都已经忘记了;是时间好好回炉一下了,说实话干读数据机构这本书还是挺枯燥而且这本书原理性比较多,有一定的难度。这不刚看到逆波兰式废了好大劲才搞懂,老了。。。

逆波兰式

逆波兰式(Reverse Polish notation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后)

一个表达式E的后缀形式可以如下定义:
(1)如果E是一个变量或常量,则E的后缀式是E本身。
(2)如果E是E1 op E2形式的表达式,这里op是如何二元操作符,则E的后缀式为E1'E2' op,这里E1'和E2'分别为E1和E2的后缀式。
(3)如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式。
如:我们平时写a+b,这是中缀表达式,写成后缀表达式就是:ab+
(a+b)*c-(a+b)/e的后缀表达式为:
(a+b)*c-(a+b)/e
→((a+b)*c)((a+b)/e)-
→((a+b)c*)((a+b)e/)-
→(ab+c*)(ab+e/)-
→ab+c*ab+e/-

算法实现

将一个普通的中序表达式转换为逆波兰表达式的一般算法是:
首先需要分配2个栈,一个作为临时存储运算符的栈S1(含一个结束符号),一个作为输入逆波兰式的栈S2(空栈),S1栈可先放入优先级最低的运算符#,注意,中缀式应以此最低优先级的运算符结束。可指定其他字符,不一定非#不可。从中缀式的左端开始取字符,逐序进行如下步骤:
(1)若取出的字符是操作数,则分析出完整的运算数,该操作数直接送入S2栈
(2)若取出的字符是运算符,则将该运算符与S1栈栈顶元素比较,如果该运算符优先级(不包括括号运算符)大于S1栈栈顶运算符优先级,则将该运算符进S1栈,否则,将S1栈的栈顶运算符弹出,送入S2栈中,直至S1栈栈顶运算符低于(不包括等于)该运算符优先级,最后将该运算符送入S1栈。
(3)若取出的字符是“(”,则直接送入S1栈顶。
(4)若取出的字符是“)”,则将距离S1栈栈顶最近的“(”之间的运算符,逐个出栈,依次送入S2栈,此时抛弃“(”。
(5)重复上面的1~4步,直至处理完所有的输入字符
(6)若取出的字符是“#”,则将S1栈内所有运算符(不包括“#”),逐个出栈,依次送入S2栈。
完成以上步骤,S2栈便为逆波兰式输出结果。不过S2应做一下逆序处理。便可以按照逆波兰式的计算方法计算了!

代码程序

//'1 + 2 * 3 + (4 * 5 + 6) * 7'function ReversePolish() {this.operatorStack = [];// this.operator = ['+', '-', '*', '/', '(', ')'];this.operator = {'+': 1,'-': 1,'*': 2,'/': 2,'(': 10,')': 10};this.rp = [];
}ReversePolish.prototype.convert = function(str) {debugger;// ('15 + 2 * 3 + (4 * 5 + 6) * 7').trim().replace(/\s+/g, '').split(/([\+|\-|\*|\/|\(|\)])/)// ["15", "+", "2", "*", "3", "+", "", "(", "4", "*", "5", "+", "6", ")", "", "*", "7"]
  str.trim().replace(/\s+/g, '').split(/([\+|\-|\*|\/|\(|\)])/).filter(e => !!e).forEach(e => {if (/[0-9]/g.test(e)) { // 数字直接放入逆波兰式数组this.rp.push(e);} else {if (this.operatorStack.length === 0) {// 操作符栈为空直接压入栈this.operatorStack.push(e);} else {if (e === '(') { // 左括号直接入栈this.operatorStack.push(e);} else if (e === ')') { // 右括号弹出所有的操作符进入逆波兰数组,直至遇到 (, (不进入逆波兰数组let op = this.operatorStack.pop();while(op !== '(') {this.rp.push(op);op = this.operatorStack.pop();}// this.operatorStack.pop();} else { // 遇到其他操作符则弹出所有栈顶元素,直至遇到优先级更低的操作符,但是不处理(let op = this.operatorStack.pop();while(op && this.operator[op] >= this.operator[e] && op !== '(') {this.rp.push(op);op = this.operatorStack.pop();}if (op) {this.operatorStack.push(op);}this.operatorStack.push(e);}}}});// 运行结束后将所有的操作符栈弹出let op = this.operatorStack.pop();while(op) {this.rp.push(op);op = this.operatorStack.pop();}console.log(this.rp.join(' '));
};//15 2 3 * + 4 5 * 6 + 7 * +
ReversePolish.prototype.eval = function(){let numberStack = [];this.rp.forEach(e => {if (/[0-9]/g.test(e)) {numberStack.push(Number(e));} else if (this.operator[e]) {let n2 = numberStack.pop();let n1 = numberStack.pop();switch(e) {case '+':numberStack.push(n1 + n2);break;case '-':numberStack.push(n1 - n2);break;case '*':numberStack.push(n1 * n2);break;case '/':numberStack.push(n1 / n2);}}});return numberStack.pop();
}let rp = new ReversePolish();
rp.convert('15 + 2 * 3 + (4 * 5 + 6) * 7');
rp.eval();

  感觉逆波兰式不仅是一种方法,更是一种思想,逆波兰式这种计算方法没有必要知道任何运算符优先规则。就像我们实际业务中有很多逻辑判断、各种优先级的场景,是否也可以使用逆波兰式的思想来解决?上面的例子也是比较简单的情况,没有考虑运算符的执行顺序,对于2^2^3这个种,实际是等于2^8等于256,而不是4^3=64.

转载于:https://www.cnblogs.com/dojo-lzz/p/9000223.html

数据结构——逆波兰式相关推荐

  1. c语言数据结构逆波兰算法,[分享]表达式二叉树逆波兰式的转换程序源代码(C++)...

    [分享]表达式二叉树逆波兰式的转换程序源代码(C++) RT,这是我两年前学数据结构时的作品. 拿出来给大家分享. ps:当时才学C++,代码写的不好,见笑了./*将中缀式转换为表达式树,并打印逆波兰 ...

  2. 【数据结构】波兰式、逆波兰式与中缀表达式

    目录 中缀表达式 后缀表达式 前缀表达式 计算后缀表达式结果 计算机实现中缀转后缀 中缀表达式  中缀表达式即运算符在操作数之间的表达式,常见表达式均为中缀表达式.因为中缀表达式更利于人们理解以及计算 ...

  3. 线性数据结构的实现与应用_双端队列_逆波兰式_呼叫中心_XAUAT_(原问题自杜克大学Duke University cps110 C++ Stacks and Queues and Lists)

    求收藏求转发! 附实验报告链接: https://blog.csdn.net/weixin_43781565/article/details/106507340 提供DOC资源  https://do ...

  4. PHP中的逆波兰式应用

    定义 逆波兰式(Reverse Polish notation,RPN,或逆波兰记法),也叫后缀表达式(将运算符写在操作数之后)  如:我们平时写a+b,这是中缀表达式,写成后缀表达式就是:ab+  ...

  5. 逆波兰式与表达式求值

    何为波兰式?何为逆波兰式? 如何与表达式求值联系起来? 波兰式.逆波兰式是数据结构和编译原理里面提到的知识点,我们平时的运算式都是这样的 2 + 3 * (5 - 1)-10(中缀表达式),这样表达式 ...

  6. 逆波兰式是什么(以及dc计算器如何使用)

    最近看文档看到逆波兰式(Reverse Polish notation或者reverse-polish,RPN)就去查询了一下.如果需要较为详细的解释看这个链接:https://mathworld.w ...

  7. 编译原理 | 实验四 | 逆波兰式

    目录 一.问题分析 二.算法思想 1.关于分词器 2.关于逆波兰式分析器: 三.实现代码 1.头文件  &  类视图 2.预处理部分 3.逆波兰分析过程 4.计算,输出部分 四.总结 一.问题 ...

  8. java逆波兰式求值_波兰式、逆波兰式与表达式求值

    波兰式.逆波兰式是<数据结构>课程中讲解关于栈的时候提到的,栈是很简单的一种数据结构.但是这些理论的提出却是计算机早期发展领域的重大突破,值得仔细回味. 1. 中缀表达式 我们在数学中学到 ...

  9. 编译原理逆波兰式实验java_【实验三】—— 逆波兰式生成实验报告

    实验三 逆波兰式生成实验报告 一.实验名称:逆波兰式生成 二.仪器.设备:计算机 三.参考资料:<编译原理教程>习题解析与上机指导(西安电子科技大 胡元义等) 四.实验目的:将非后缀式用来 ...

最新文章

  1. 同时运行多个scrapy爬虫的几种方法(自定义scrapy项目命令)
  2. SpringBoot+Vue+Echarts实现双柱体柱状图
  3. mysql create很多table,SQL CREATE TABLE 语句
  4. CSS3制作一个简单的进度条
  5. “劣质”的PHP代码简化
  6. java怎样输出一个文件夹,java合并一个文件夹下所有txt文件,输出到另一个txt,...
  7. 史上最全的 iOS测试工具集锦(自动化、性能)
  8. 三维GIS引擎平台设计
  9. 计算机cpu架构是什么意思,「电脑小白必备」一分钟快速了解CPU
  10. leetcode刷题java之739. 每日温度
  11. 脱水冷冻干燥宠物食品的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  12. bde oracle 商友的流程_BorlandC++使用BDE访问Oracle的方法
  13. 0x00007FFEB5D49149 处(位于 Project1.exe 中)有未经处理的异常: Microsoft C++ 异常: cv::Exception,位于内存位置 0x000
  14. latex初学者的经验
  15. C语言程序设计课程设计(服装销售管理系统)
  16. 来说一说毕达哥拉斯定理
  17. POI操作Word文档工具
  18. 佛说,今生你嫁的人,是前世葬你的人
  19. 腾讯 Angel Graph 图计算框架在智能风控中的应用
  20. 【51Nod】1266 蚂蚁

热门文章

  1. 推荐一个高质量的git命名查询和学习的github仓库git-recipes
  2. 如何处理错误消息Please install the Linux kernel header files
  3. Windows设置HTML,windows怎么添加静态路由
  4. vue 如何将参数放到连接上_通过Vue路由传参的两种方式及Vue组件中接收参数的方式...
  5. 世界上没有一模一样的东西_世界上存在两根同时点燃同时燃尽一模一样的蜡烛吗?...
  6. mongodb的id的唯一性_mongodb中的objectid是collection中唯一,还是全db唯一,还是全宇宙唯一?...
  7. mysql optimize 作用_mysql optimize table
  8. ant vue 设置中文_Ant Design Vue 添加区分中英文的长度校验功能
  9. tcp压测工具_【解决方案】性能压测及分析调优实践
  10. 二叉树的锯齿形层序遍历Python解法