后缀表达式的算法和实现

合集下载

3.3-1 表达式及后缀表达式求值

3.3-1 表达式及后缀表达式求值

堆栈和队列Content堆栈1队列2表达式计算3递归4PART THREE表达式计算•表达式的概念•后缀表达式求值•中缀表达式到后缀表达式的转换•中缀表达式:操作符在两个操作数之间的表达式•前缀表达式:操作符在两个操作数之前的表达式•后缀表达式:操作符在两个操作数之后的表达式逆波兰表达式(Reverse Polish notation ,RPN ),J. Lukasiewicz 1929示例:a + b 示例:+ a b 示例:a b +表达式:由操作数、操作符(+、-、*、\等)和界限符(括号等)组成•中缀表达式a + ( b –c )a + ba b +a b c -+计算的顺序由界符、操作符优先级决定计算的顺序只取决于操作符的扫描顺序•后缀表达式VS.对比:•操作数的顺序相同,而操作符的顺序不同;•前者的不同操作符的运算优先级存在差异,后者的所有操作符的运算优先级相同;•前者可以有界限符,后者没有界限符;后缀表达式求值算法(利用堆栈实现):1.从左往右顺序依次扫描后缀表达式中的元素:•若当前扫描元素是操作数,则将操作数进栈;•若当前扫描元素是操作符,则从栈中弹出两个操作数,并执行该操作符指定的运算,然后将计算结果进栈;2.当表达式扫描结束,弹出栈顶数据,该数据即为计算结果。

6 4 2 -/ 3 2 * + 6-24/32*+6/(4-2)+3*2= 9算法(利用堆栈实现):1.从左往右顺序依次扫描后缀表达式中的元素:•若当前扫描元素是操作数,则将操作数进栈;•若当前扫描元素是操作符,则从栈中弹出两个操作数,并执行该操作符指定的运算,然后将计算结果进栈;2.当表达式扫描结束,弹出栈顶数据,该数据即为计算结果。

6 4 2 -/ 3 2 * +6-24/32*+42=2算法(利用堆栈实现):1.从左往右顺序依次扫描后缀表达式中的元素:•若当前扫描元素是操作数,则将操作数进栈;•若当前扫描元素是操作符,则从栈中弹出两个操作数,并执行该操作符指定的运算,然后将计算结果进栈;2.当表达式扫描结束,弹出栈顶数据,该数据即为计算结果。

后缀式计算过程

后缀式计算过程

后缀式计算过程
嘿,朋友们!今天咱就来讲讲这后缀式计算过程。

啥是后缀式呢?简单来说,就是一种特别的计算表达方式。

咱平常做算术,都是先加减后乘除对吧,但后缀式可不一样。

就好比咱去超市买东西排队结账。

平常的计算方式就像是大家按先来后到排队,一个一个来。

而后缀式呢,就像是把这些商品和计算符号都扔到一个大框里,最后再一起算。

比如说,平常我们算 3 加 5 乘 2,得先算 5 乘 2 等于 10,再加上 3 得13。

但后缀式呢,就变成了3 5 2 * +。

先把3、5、2 放进去,看到乘号就先算 5 乘 2,得到 10,再看到加号,就把 3 和 10 加起来,还是13。

这可有意思了吧!那后缀式有啥好处呢?它能让计算更清晰,不容易出错呀。

我记得有一次,我给小侄子辅导数学作业,那算式写得密密麻麻,他看得晕头转向。

我就想,要是用后缀式,不就简单多了嘛。

于是我给他讲了后缀式,嘿,他一下子就明白了。

再比如说,我们在电脑编程里也常用到后缀式呢。

电脑可不像咱人脑,它得按照特定的规则来计算。

而后缀式就能让电脑的计算更准确、更高效。

其实呀,这后缀式就像一把特别的钥匙,能打开计算世界里的一扇新门。

让我们能从不同的角度去看计算,发现它的奇妙之处。

在生活中,我们也可以多试试用后缀式的思维去想问题。

有时候,换个角度,也许就能找到新的解决办法。

所以呀,朋友们,不妨多了解了解这后缀式计算过程,说不定哪天就能派上大用场呢!它能让我们的计算变得更有趣、更轻松。

试试吧,你会发现一个不一样的计算天地!。

基于栈的后缀算术表达式求值c语言

基于栈的后缀算术表达式求值c语言

基于栈的后缀算术表达式求值c语言1. 引言1.1 概述本文将讨论基于栈的后缀算术表达式求值的实现过程。

后缀算术表达式(也称为逆波兰表达式)是一种无需括号即可进行运算的表达式表示方法,它将操作符置于操作数之后。

相较于传统的中缀表达式,在计算机程序中处理后缀表达式更为高效和简洁。

1.2 文章结构文章分为五个主要部分:引言、栈的概念及原理、后缀算术表达式的定义和转换、基于栈的后缀算术表达式求值算法实现以及结论与总结。

在引言部分,我们将首先介绍本文的概述和目标,对后续内容进行简要说明。

1.3 目的通过本文,我们旨在让读者了解栈数据结构的基本概念和原理,并且掌握如何利用栈来实现对后缀算术表达式进行求值的算法。

同时,我们将介绍后缀算术表达式的定义和转换方法,并给出基于栈实现该计算方式的详细步骤与示例代码。

通过深入研究并学习这些内容,读者可以加深对栈数据结构和后缀算术表达式的理解,并且能够应用所学知识解决实际问题。

本文不仅适用于计算机科学或相关专业的学生,也适合对数据结构和算法感兴趣的读者阅读和学习。

2. 栈的概念及原理2.1 栈的定义栈是一种具有特定限制条件的线性数据结构,它具备“先进后出”(Last-In-First-Out,LIFO)的特性。

栈可以看作是一个容器,其中可以存储各种类型的数据。

与实际生活中的堆栈类似,栈只允许在其末尾进行插入和删除操作。

在栈中,最后加入的元素首先被访问和处理。

这是由于栈内元素之间的相对位置关系决定的。

插入操作称为“压栈”(Push),删除操作称为“弹栈”(Pop),而从栈顶读取元素或获取栈顶元素但不删除它称为“查看”(Peek)。

2.2 栈的基本操作推入元素:将一个元素添加到栈顶。

如果已经存在满员条件,则无法执行此操作。

弹出元素:从栈顶移除一个元素,并返回移除的值。

如果没有任何元素存在,则无法执行此操作。

查看栈顶元素:获取位于栈顶处的元素值,但不对其进行删除。

判断是否为空:检查栈是否为空。

中最表达式-后缀表达式

中最表达式-后缀表达式
N=N/B;
}
while(!StackEmpty(&S)){?//栈非空时退栈输出
i=Pop(&S);
printf("%d",i);
}
}
例,求后缀表达式:1 2 + 8 2 - 7 4 - / *的值,
栈的变化情如下:
步骤
栈中元素
说明
1
1
1进栈
2
12
2进栈
3
遇+号退栈2和1
4
3
1+2=3的结果3进栈
5
38
8进栈
6
382
2进栈
7
3
遇-号退栈2和8
17
6
扫描完毕,运算结束
从上可知,最后求得的后缀表达式之值为6,与用中缀表达式求得的结果一致,但后缀式求值要简单得多。
五、中缀表达式变成等价的后缀表达式的算法
将中缀表达式变成等价的后缀表达式,表达式中操作数次序不变,运算符次序发生变化,同时去掉了圆括号。转换规则是:设立一个栈,存放运算符,首先栈为空,编译程序从左到右扫描中缀表达式,若遇到操作数,直接输出,并输出一个空格作为两个操作数的分隔符;若遇到运算符,则必须与栈顶比较,运算符级别比栈顶级别高则进栈,否则退出栈顶元素并输出,然后输出一个空格作分隔符;若遇到左括号,进栈;若遇到右括号,则一直退栈输出,直到退到左括号止。当栈变成空时,输出的结果即为后缀表达式。将中缀表达式(1+2)*((8-2)/(7-4))变成等价的后缀表达式。
例如,后缀表达式(abc*+def*/-)的求值
四、后缀表达式的求值的算法

(完整版)数学表达式计算(c语言实现)

(完整版)数学表达式计算(c语言实现)

一、设计思想计算算术表达式可以用两种方法实现:1.中缀转后缀算法此算法分两步实现:先将算术表达式转换为后缀表达式,然后对后缀表达式进行计算.具体实现方法如下:(1)中缀转后缀需要建一个操作符栈op和一个字符数组exp,op栈存放操作符,字符数组用来存放转换以后的后缀表达式。

首先,得到用户输入的中缀表达式,将其存入str数组中。

对str数组逐个扫描,如果是数字或小数点,则直接存入exp数组中,当扫描完数值后,在后面加一个#作为分隔符。

如果是操作符,并且栈为空直接入栈,如果栈不为空,与栈顶操作符比较优先等级,若比栈顶优先级高,入栈;如果比栈顶优先级低或相等,出栈将其操作符存到exp数组中,直到栈顶元素优先等级低于扫描的操作符,则此操作符入栈;如果是左括号,直接入栈,如果是右括号,出栈存入exp数组,直到遇到左括号,左括号丢掉。

然后继续扫描下一个字符,直到遇到str中的结束符号\0,扫描结束。

结束后看op栈是否为空,若不为空,继续出栈存入exp数组中,直到栈为空.到此在exp数组最后加结束字符\0。

我们就得到了后缀表达式。

(2)后缀表达式计算此时需要一个数值栈od来存放数值。

对exp数组进行逐个扫描,当遇到数字或小数点时,截取数值子串将其转换成double类型的小数,存入od栈中。

当遇到操作符,从栈中取出两个数,进行计算后再放入栈中。

继续扫描,知道扫描结束,此时值栈中的数值就是计算的结果,取出返回计算结果。

2。

两个栈实现算法此算法需要两个栈,一个值栈od,一个操作符栈op。

将用户输入的数学表达式存入str数组中,对其数组进行逐个扫描。

当遇到数字或小数点,截取数值子串,将其转换成double类型的数值存入od栈中;当遇到左括号,直接入op栈;遇到右括号,op栈出栈,再从值栈od中取出两个数值,计算将其结果存入值栈中,一直进行此操作,直到操作符栈栈顶为左括号,将左括号丢掉。

如果遇到操作符,若op栈为空,直接入栈;若栈不为空,与栈顶元素比较优先等级,若比栈顶操作符优先等级高,直接入op栈,如果低于或等于栈顶优先等级,op栈出栈,再从值栈中取出两个数值,计算将其结果存入值栈中,一直进行此操作,直到栈顶优先等级低于扫描的操作符等级,将此操作符入op 栈。

后缀表达式求值过程

后缀表达式求值过程

后缀表达式求值过程嘿,朋友!今天咱们来唠唠后缀表达式求值这个超有趣的事儿。

你可能会想,这后缀表达式是啥呀?就像你看到一个神秘的密码,其实只要掌握了方法,求值就像解开密码锁一样简单又好玩。

我先给你说说啥是后缀表达式吧。

咱平常看到的表达式,像“3 + 4”这种中缀表达式,操作符在中间。

而后缀表达式呢,操作符在操作数的后面,就像“3 4 +”。

这看起来有点怪,可它在计算机处理起来可就方便多啦。

那怎么求值呢?咱得有个小工具,那就是栈。

栈就像一个小盒子,不过这个小盒子有点特别,先放进去的东西后拿出来,就像你往一个窄口瓶子里塞东西,先塞进去的在底下,最后才能拿出来。

比如说咱们要计算“4 5 * 6 +”这个后缀表达式的值。

我和我那聪明的小伙伴小明就开始啦。

小明负责操作栈,我来指挥。

首先看到“4”,小明就把4这个数字放到栈里。

这就像把一个小宝贝放进那个神秘的盒子里。

接着看到“5”,小明也把5放进栈里。

现在栈里就有4和5啦,就像两个小伙伴在盒子里安静地待着。

然后看到“*”这个操作符,这时候就像魔法要开始啦。

小明从栈里拿出5和4(注意哦,是先拿5,因为栈的特性),然后计算4乘以5等于20,再把20放进栈里。

哇,这就像把两个小伙伴融合成了一个超级小伙伴呢!再看到“6”,小明又把6放进栈里。

现在栈里有20和6啦。

最后看到“+”,小明又从栈里拿出6和20,计算20加6等于26,这就是最后的结果啦。

是不是感觉很神奇呢?就像一场奇妙的数学之旅。

再来看一个复杂点的例子吧。

像“3 4 + 2 * 5 -”。

我和我的另一个朋友小花来操作这个。

小花可认真啦。

先看到“3”,放进栈里,再看到“4”,也放进栈里。

看到“+”的时候,小花从栈里拿出4和3,计算3加4等于7,把7放进栈里。

这时候就像我们搭建了一个小积木塔的一部分。

接着看到“2”,放进栈里。

看到“*”的时候,小花从栈里拿出2和7,计算7乘以2等于14,再把14放进栈里。

最后看到“5”,放进栈里,看到“ - ”的时候,小花从栈里拿出5和14,计算14减5等于9。

C++:后缀表达式

C++:后缀表达式

C++:后缀表达式1.基本概念后缀表⽰法也叫逆波兰表⽰法(前缀就是波兰表⽰法),由于所有的操作符都在操作数的后⾯,所以被称为后缀表⽰法。

中缀表⽰法的操作符在操作数之间,也是最符合⼈的逻辑。

前缀表⽰法的操作符在操作数之前,它和后缀表⽰法⼀样,都是为了⽅便计算机计算,因为在后缀或前缀中没有括号,也不存在优先级处理的问题,直接利⽤栈进⾏计算。

⽰例:中缀:5+(1+2)*4-3后缀:512+4*+3-2.中缀表⽰转后缀表⽰中缀转后缀可以从左向右扫描表达式,然后按照规则进⾏处理,对于中缀表达式a+(b+c)*d-e的转换步骤:(1). ⾸先初始化两个栈:输出栈rpn_和操作符栈rpn_stack(2). 从左⾄右扫描表达式,遇到操作数则直接压⼊输出栈,在遇到a时,由于是操作数,将"a"压⼊rpn_(3). 继续扫描,遇到操作符时,如果该操作符优先级⾼于rpn_stack栈顶的操作符,则直接压⼊rpn_stack,如果同级或低于栈顶操作符,则将栈中操作符依次弹出(同时压⼊输出栈)直到遇到⽐当前操作符优先级低的(或者遇到了"("),然后压⼊操作符。

(注意,对于操作符"(",只有")"才能将其弹出,其他情况不弹出"(")。

现在我们扫描到了"+",由于当前的操作符栈空,直接压⼊。

(4). 然后读取到"(",由于它的优先级是最⾼的,只要遇到就直接压⼊栈。

(5). 然后读取到操作数"b",压⼊输出栈 rpn_。

(6). 继续读取到 "+" ,当前操作符栈的栈顶是"(",因为只有")"才能将其弹出,所以"+"⼊栈。

(7). 读取的"c"压⼊输出栈。

(8). 读取到了")",此时开始将操作符栈的操作符依次弹出(同时压⼊输出栈),直到遇到第⼀个"(",将"("弹出。

C#算术表达式求值(后缀法),看这一篇就够了

C#算术表达式求值(后缀法),看这一篇就够了

C#算术表达式求值(后缀法),看这⼀篇就够了⼀、种类介绍算术表达式有三种:前缀表达式、中缀表达式和后缀表达式。

⼀般⽤的是中缀,⽐如1+1,前后缀就是把操作符移到前⾯和后⾯,下⾯简单介绍⼀下这三种表达式。

1、前缀表⽰法前缀表⽰法⼜叫波兰表⽰法,他的操作符置于操作数的前⾯(例:+ 1 2),是波兰数学家扬·武卡谢维奇1920年代引⼊的,⽤于简化命题逻辑。

因为我们⼀般认为操作符是在操作数中间的,所以在⽇常⽣活中⽤的不多,但在计算机科学领域占有⼀席之地。

⼀般的表⽰法对计算机来说处理很⿇烦,每个符号都要考虑优先级,还有括号这种会打乱优先级的存在,将使计算机花费⼤量的资源进⾏解析。

⽽前缀表⽰法没有优先级的概念,他是按顺序处理的。

举个例⼦:9-2*3这个式⼦,计算机需要先分析优先级,先乘后减,找到2*3,再进⾏减操作;化成前缀表⽰法就是:- 9 * 2 3,计算机可以依次读取,操作符作⽤于后⼀个操作数,遇到减就是让9减去后⾯的数,⽽跟着9的是乘,也就是说让9减去乘的结果,这对计算机来说很简单,按顺序来就⾏了。

2、中缀表⽰法这也就是我们⼀般的表⽰法,他的操作符置于操作数的中间(例:1 + 2),前⾯也说过这种⽅法不容易被计算机解析,但他符合⼈们的普遍⽤法,许多编程语⾔也就⽤这种⽅法了。

在中缀表⽰法中括号是必须有的,要不然运算顺序会乱掉。

3、后缀表⽰法后缀表⽰法⼜叫逆波兰表⽰法,他的操作符置于操作数的后⾯(例:1 2 +),他和前缀表⽰法都对计算机⽐较友好,但他很容易⽤堆栈解析,所以在计算机中⽤的很多。

他的解释过程⼀般是:操作数⼊栈;遇到操作符时,操作数出栈,求值,将结果⼊栈;当⼀遍后,栈顶就是表达式的值。

因此逆波兰表达式的求值使⽤堆栈结构很容易实现,且能很快求值。

注意:逆波兰记法并不是简单的波兰表达式的反转。

因为对于不满⾜交换律的操作符,它的操作数写法仍然是常规顺序,如,波兰记法/ 6 3的逆波兰记法是6 3 /⽽不是3 6 /;数字的数位写法也是常规顺序。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

数据结构—中缀表达式转后缀表达式算法及实现—栈的应用—计算表达式(C++代...理论:(这部分很重要,看明白了,可以写出实现算法)表达式的表示形式有中缀、前缀和后缀3中形式。

中缀表达式按操作符的优先级进行计算(后面代码实现只包括+、-、*、\,小括号),即数学运算。

后缀表达式中只有操作数和操作符。

操作符在两个操作数之后。

它的计算规则非常简单,严格按照从左到右的次序依次执行每一个操作。

每遇到一个操作符,就将前面的两个数执行相应的操作。

由后缀表达式计算中缀表达式原理:计算机处理后缀表达式求值问题是比较方便的,即将遇到的操作数暂存于一个操作数栈中,凡是遇到操作数,便从栈中pop出两个操作数,并将结果存于操作数栈中,直到对后缀表达式中最后一个操作数处理完,最后压入栈中的数就是后最表达式的计算结果。

中缀表达式转换为等价的后缀表达式中缀表达式不方便与计算机处理,通常要讲中缀表达式转换为一个与之等价的后缀表达式。

等价是指两个表达式的计算顺序和计算结果完全相同。

中缀表达式:0.3/(5*2+1)#的等价后缀表达式是:0.3 5 2 * 1 + /#仔细观察这两个等价的表达式可知,操作数的出现次序是相同的,但运算符的出现次序是不同的。

在后缀表达式中,运算符的出现次序是实际进行操作的次序;在中追表达式中,由于受到操作符的优先级和括号的影响,操作符出现次序与实际进行操作的次序很可能是不一样的。

算法描述:将中缀表达式转换为等价的后缀表达式的过程要使用一个栈放“(”,具体可以按照下面的方式进行。

(1)从左到右一次扫描中缀表达式的每一个字符,如果是数字字符和圆点“.”则直接将它们写入后缀表达式中。

(2)如果遇到的是开括号“(”,则将它们压入一个操作符栈(不需要与栈顶操作符相比较),它表明一个新的计算层次的开始,在遇到和它匹配的闭括号“)”时,将栈中的元素弹出来并放入后缀表达式中,直到栈顶元素为“(”时,将栈顶元素“(”弹出(不需要加入后缀表达式),表明这一层括号内的操作处理完毕。

(3)如果遇到的是操作符,则将该操作符和操作符栈顶元素比较:1、当所遇到的操作符的优先级小于或等于栈顶元素的优先级时,则取出栈顶元素放入后缀表式,并弹出该栈顶元素,反复执行直到栈顶元素的优先级小于当前操作符的优先级;2、当所遇到的操作符的优先级大于栈顶元素的优先级的时则将它压入栈中。

(4)重复上述步骤直到遇到中缀表达式的结束符标记“#”,弹出栈中的所有元素并放入后缀表达式中,转换结束。

如果有算法方描述的不清楚,敬请网友指出,本人表达能力较差,欢迎提出问题。

C++ 代码描述算法:(可以识别小数点,括号,实现加减乘除四则运算,可以处理任意长度的操作数,包括小数)// 把中缀表达式转换为后缀表达式,返回后缀表达式的长度(包括空格)void postfix(char pre[] ,char post[],int &n){int i = 0 ,j=0;Stack<char> stack; //使用的是类模板,在下篇文章给出stack.init(); // 初始化存储操作符的栈stack.push('#'); // 首先把结束标志…#‟放入栈底while(pre[i]!='#'){if((pre[i]>='0' && pre[i] <='9')||pre[i] =='.') // 遇到数字和小数点直接写入后缀表达式{post[j++] = pre[i];n++;}else if (pre[i]=='(') // 遇到“(”不用比较直接入栈stack.push(pre[i]);else if(pre[i] ==')') // 遇到右括号将其对应左括号后的操作符(操作符栈中的)全部写入后缀表达式{while(stack.gettop()!='('){post[j++] = stack.pop();n++;}stack.pop(); // 将“(”出栈,后缀表达式中不含小括号}else if (isoperator(pre[i])){post[j++] = ' '; // 用空格分开操作数(n++;while(priority(pre[i]) <= priority(stack.gettop())){// 当前的操作符小于等于栈顶操作符的优先级时,将栈顶操作符写入到后缀表达式,重复此过程post[j++] = stack.pop();n++;}stack.push(pre[i]); // 当前操作符优先级大于栈顶操作符的优先级,将该操作符入栈}i++;}while(stack.top) // 将所有还没有出栈的操作符加入后缀表达式{post[j++] = stack.pop();n++;}}bool isoperator(char op){switch(op){case '+':case '*':case '/':return 1;default :return 0;}}// 判断是否为运算符int priority(char op) {switch(op){case '#':return -1;case '(':return 0;case '+':case '-':return 1;case '*':case '/':return 2;default :return -1;}}// 求运算符优先级int priority(char op) {switch(op){return -1;case '(':return 0;case '+':case '-':return 1;case '*':case '/':return 2;default :return -1;}}// 将数字字符串转变成相应的数字double readnumber(char str[],int *i){double x=0.0;int k = 0;while(str[*i] >='0' && str[*i]<='9') // 处理整数部分{x = x*10+(str[*i]-'0');(*i)++;}if(str[*i]=='.') // 处理小数部分{(*i)++;while(str[*i] >= '0'&&str[*i] <='9'){x = x * 10 + (str[*i]-'0');(*i)++;k++;}}while(k!=0){x /= 10.0;k--;}return x;}// 由后缀表达式字符串计算相应的中值表达式的值double postfix_value(char post[]){Stack<double> stack; // 操作数栈stack.init();int i=0 ;double x1,x2;while(post[i] !='#'){if(post[i] >='0' && post[i] <='9')stack.push(read_number(post,&i));else if(post[i] == ' ')i++;else if (post[i] =='+'){x2 = stack.pop();x1 = stack.pop();stack.push(x1+x2);i++;}else if (post[i] =='-'){x2 = stack.pop();x1 = stack.pop();stack.push(x1-x2);i++;}else if (post[i] =='*'){x2 = stack.pop();x1 = stack.pop();stack.push(x1*x2);i++;}else if (post[i] =='/'){x2 = stack.pop();x1 = stack.pop();stack.push(x1/x2);i++;}}return stack.gettop();}// main()函数void main(){char pre[] ="22/(5*2+1)#";char post[100] ;cout <<"中缀表达式为:"<< pre << endl;int n =0; // 返回后缀表达式的长度postfix(pre,post,n);cout <<"后缀表达式为:";for( int i =0 ;i < n ;i++)cout << post[i] ;cout << "\n由后缀表达式计算出的数值结果: "; cout << postfix_value(post) << endl;system("pause");}运行结果:。

相关文档
最新文档