一、三者的概念(参考维基百科)

1.1中缀表达式

中缀表达式是符合人类直觉的一种表达方式,其特点是操作符(二元操作符)在中间,操作数在两侧。

例如 3 + 4 ,   5 - 6 * 7,     (5 - 6) *7等。括号的存在会影响计算步骤的执行。

1.2前缀表达式(又称波兰表达式)

前缀表达式(以及后缀表达式)是符合计算机思维的一种表达方式。

将1.1的几个中缀表达式转换成前缀表达式如下:

+ 3 4 ,   - 5 * 6 7,     * - 5 6 7

这种表达式有一个特点,由它的发明人波兰数学家扬·武卡谢维奇指出,这种方式是无需括号的表达方式,即括号不影响计算顺序

如 * (- 5 6) 7 与 * - 5 6 7是一样的。这里需要说明的是,无需括号的这种特点是有适用范围的,当操作符作用的操作数的个数可变时,如阶乘一元 + - * /等为二元时,就需要用括号来表示操作顺序了。

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

后缀表达式也是符合计算机思维的一种表达方式,与前缀表达式具有同样的特点,只是顺序相反(在编程实现上还有些细微差别,),但是我们在编程实现的时候对一个表达式的字符串,采用后缀表达的话,字符串从前往后读取并处理,符合我们的编程习惯,所以常常以如何求值后缀表达式或将中缀表达式转换成后缀表达式来作为教学。

将1.1的几个中缀表达式转换成前缀表达式如下:

3 4 +,    5 6 7 * - , 5 6 - 7 *

二、中缀表达式与后缀表达式的比较(基于二元操作符下的讨论)

2.1中缀表达式的朴素算法

已知运算符是有运算顺序的,对于一个没有括号的表达式(操作数记为n, 操作符记为op):

n1  op1  n2  op2  n3  op3  n4  ...  opk  nk+1

我们知道,当计算机线性读取(即从左到右读取该字符串时)其遇到op1,此时它并不能确定是否可以立即做运算,因为op1优先级不一定是最高的,所以它必须得遍历op1 到 opk找到最高级的opj,并做(nj opj nj+1)的运算。

这一步骤可归纳如下:遍历整个字符串,找到当前最高级的操作符opj,进行运算,所有运算符均参与运算。

每一步的时间复杂度为(假设当前字符串长度为n): n, 下一步则为n - 3 + 1 = n -2。

所以整个算法复杂度为等差数列求和为O(n^2)。

这也是为什么符合人类直觉的表达式却不适合用计算机来处理。

2.2具有迷惑性的中缀表达式求值算法(本质上是将中缀表达式转换成后缀表达式再处理的一种方式)

/*
此算法摘自《中缀和后缀算术表达式的分析比较》刘爱贵  高能物理研究所计算中心 2003年
*/
int middexpression(char *exp){stack<int> *opnd=new(stack<int>);   // 操作数栈stack<char> *optr=new(stack<char>);  // 运算符栈char ch=*exp;int x=0,y,z;int result;optr->push('#');while(ch!='#'||optr->gettop()!='#')// 字符扫描完毕且运算符栈仅有‘#’时运算结束{if(!Operator(ch)){x=x*10+(int)(ch)-48;if(Operator(*(exp+1))){opnd->push(x);x=0;}ch=*++exp;}else{switch(Precede(optr->gettop(),ch)) {case '<':// 栈顶元素优先权低optr->push(ch);ch=*++exp;break;case '=':// 脱括号并接收下一字符optr->pop();ch=*++exp;break;case '>':// 退栈并将运算结果入栈,但不取下一表达式字符x=opnd->pop();y=opnd->pop();z=calc(y,optr->pop(),x);opnd->push(z);x=0;break;}}}result = opnd->pop();return(result);
}

这里我们重点关注一下该算法时如何处理操作符的(此处摘抄参考文章的原文):

为了实现算符优先算法,要使用两个工作栈。一个称为OPTR, 用以寄存运算符;另一个称为OPND ,用以寄存操作数或运算结果,它的基本思想于后缀表达式计算的不同在于:当读取到运算符时并不可能作相应运算,必须先比较运算符栈中栈顶元素与当前运算符的优先级。若为‘< ’则运算符入栈;若为‘=’则说明是一对括号,需脱括号;若‘> ’则作相应运算并将结果入栈。

这里再列出一下将中缀表达式转换成后缀表达式的算法(摘自将中缀表达式转化为后缀表达式):

规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于栈顶符号(乘除优先加减)则栈顶元素依次出栈并输出,并将当前符号进栈,若是左括号或优先级高于或等于栈顶符号则直接进栈,一直到最终输出后缀表达式为止。

这里可以看到所谓的上述两个算法对操作符的处理其实是大同小异的。只不过所谓的中缀表达式求值算法将中缀表达式转换成后缀表达式的同时,也同在进行操作符的运算了。我认为其具有迷惑性的原因在于,不少博客用中缀表达式求值算法为该算法命名,如果不去解构该算法的话,会有这样一种迷惑,为什么中缀表达式求值算法已经是O(n)的复杂度了,我们还需要去讨论后缀表达式。但是通过结构该算法后,我们可以看到这个算法其实就是将中缀表达式转换成后缀表达式与后缀表达式的计算结合在了一起。

需要说明的是,我认为刘爱贵先生的这篇论文在最后的时间复杂度分析是存在些许问题的,他将该算法的复杂度分析成O(n^2)了,实际上我认为是O(n),但是我的分析过程并不是太严谨,也可能有疏漏。

2.3后缀表达式求值算法

此时的算法思想已经比较简单了:从前往后读后缀表达式,操作数则压入栈中,若遇到操作符就去操作符弹出栈顶的两个操作数做运算并将结果压入栈,直到所有操作符均遍历完。

关于中缀表达式转换成后缀表达式的方式主要有以下两种:1.调度场算法(可参考维基百科),2.2中提到的算法思想是针对二元表达式的一种简化版本。2.将中缀表达式转换成表达式树再进行后序遍历得到后缀表达式。

2.4前缀表达式与后缀表达式也是大同小异,只不过顺序有变,这里不再做分析。

Ps:本文有不少内容借鉴网上发布的博客、文章等,若有侵犯请告知,我会尽快做出合适的处理。

前缀表达式、中缀表达式、后缀表达式的区别相关推荐

  1. 前缀、中缀、后缀表达式详解

    前缀.中缀.后缀表达式详解 博客说明 文章所涉及的资料来自互联网整理和个人总结,意在于个人学习和经验汇总,如有什么地方侵权,请联系本人删除,谢谢! 介绍 前缀.中缀.后缀表达式是对表达式的不同记法,其 ...

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

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

  3. 一行文章让你搞懂什么是前缀、中缀、后缀表达式以及它们之间的相互转换

    一.什么前缀.中缀.后缀表达式(使用 8*(5+6)-1的例子) 1.中缀表达式:8*(5+6)-1:(也就是我们平常所见的运算式) 2.后缀表达式:8 5 6 + * 1 - :计算机是怎么运算的呢 ...

  4. 数据结构 - 栈 (逆波兰计算器)(栈的三种表达式)(前缀、中缀和后缀表达式,后缀也叫逆波兰表达式)(中缀表达式转后缀表达式实现步骤及完整代码)

    栈的三种表达式:前缀.中缀和后缀表达式,后缀也叫逆波兰表达式 前缀(波兰表达式) 中缀(对人来讲很好理解,对于计算机来讲就方便了,一般会把中缀表达式转换成后缀表达式) 后缀(逆波兰表达式) 计算过程 ...

  5. 前缀、中缀、后缀表达式(转载)

    关键字:概念, 前缀表达式, 前缀记法, 中缀表达式, 中缀记法, 波兰式, 后缀表达式, 后缀记法, 逆波兰式 它们都是对表达式的记法,因此也被称为前缀记法.中缀记法和后缀记法.它们之间的区别在于运 ...

  6. 前缀、中缀、后缀表达式

    关键字:概念, 前缀表达式, 前缀记法, 中缀表达式, 中缀记法, 波兰式, 后缀表达式, 后缀记法, 逆波兰式 它们都是对表达式的记法,因此也被称为前缀记法.中缀记法和后缀记法.它们之间的区别在于运 ...

  7. 前缀、中缀、后缀表达式及其相互转化的Java实现

    一.中缀表达式转换为前缀.后缀表达式 给个中缀表达式:a+b*c-(d+e) 首先根据运算符的优先级给所有运算单位加括号:((a+(b*c))-(d+e)) 将运算符号移动到对应括号的前面然后去掉所有 ...

  8. 天勤数据结构:前缀、中缀、后缀表达式的转换与计算

    第三章 栈和队列 1. 输出队列问题 2. 表达式的转换 - 手工转换 2.1 中缀表达式 转 前缀表达式 2.2 中缀表达式 转 后缀表达式 2.3 后缀表达式 转 中缀表达式 2.4 后缀表达式 ...

  9. 前缀,中缀,后缀表达式

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

  10. 数据结构与算法——前缀、中缀、后缀表达式

    目录 一.前缀表达式(波兰表达式) 二.中缀表达式 三.后缀表达式(逆波兰表达式) 1.逆波兰计算器 四.中缀转后缀 1.具体步骤 2.代码实现 一.前缀表达式(波兰表达式) 前缀表达式的运算符位于操 ...

最新文章

  1. 利用Wireshark和OSS的API文档简单实现上传和下载
  2. 20060911: 新机器·流氓软件
  3. 探索--是测试的必须品
  4. 九度OJ 朋友圈 并查集
  5. Origin绘制大小和颜色可变的3D散点图
  6. 一文说通Dotnet Core的后台任务
  7. silklabo哪个公众号有资源_微小说免费渣渣团资源公众号看大全集
  8. 使用FormData进行Ajax请求上传文件
  9. phpcms注入漏洞之文件poster.php
  10. 最简单的基于FFMPEG的封装格式转换器(致敬雷霄骅)
  11. 如何从零创建一个机器人模型
  12. 使用freemarker引擎动态生成word文件
  13. Excel应用技巧:合并单元格的排序
  14. 我为何在 CSDN 乐在其中
  15. 树莓派-4-温度CPU内存硬盘状态信息
  16. Linux命令行github,Linux命令行下使用GitHub
  17. kali使用笔记本自带无线网卡_生活日常(教你笔记本电脑如何正确使用WiFi)
  18. 5G标准核心内容:R15+R16(内含赠书福利)
  19. 《高级数据库系统》学习笔记
  20. 当清晨的第一缕阳光洒在我的头发上, 我知道,一个崭新的太阳升起来了

热门文章

  1. OpenCV双目标定
  2. 系统设计原则及技术指标
  3. php 微信小程序获取手机号_实例讲解微信小程序获取手机号授权用户登录功能...
  4. 快手2020校园招聘秋招笔试--算法B试卷
  5. 用python爬取外网
  6. php 打印curl请求的header信息和返回的header信息
  7. 系统分析与设计课程知识点总结
  8. 谷歌浏览器播放视频没有声音解决
  9. vue+ElementUI实现后台管理系统(二)
  10. 利用Python turtle库实现六角形、无角正方形的绘制