码迷,mamicode.com
首页 > 编程语言 > 详细

逆波兰算法

时间:2015-10-19 20:37:07      阅读:240      评论:0      收藏:0      [点我收藏+]

标签:

最近在学习stanford的Swift课程,里面开发了一个计算器,需要添加中缀转后缀的算法。所以在这复习下中算法思想。

一个多项式一般可以写成中缀表达式和后缀表达式来(前缀用的不多),中缀实际上就是人们正常语境中的逻辑方式,举两个例子:

a1. 1+2*3+(4+5)*6

b1. ((1+2)*3+4)*5+6 

中缀表达式机器不好理解,而后缀表达式相对来说对机器比较友好,后缀表达式又称逆波兰式 ,定义如下

一个表达式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/-
 
上面的一堆的就是如何从形式上把一个中缀变成后缀,用在a1上就是
a1. 1+2*3+(4+5)*6
a1*. (1+(2*3))+((4+5)*6)
->(1+(2,3,*))+((4,5,+)*6)
->(1,(2,3,*),+) + ((4,5,+),6,*)
->(1,2,3,*,+) + (4,5,+,6,*)
->(1,2,3,*,+) ,(4,5,+,6,*),+
->1,2,3,*,+,4,5,+,6,*,+
 
程序上如何实现呢? 一种简单的方式是用栈(用树的遍历也行,就是创建树麻烦点)
一般用两个临时栈,
S1用来放操作符,加减乘除,括号等等的。在栈底先放个#操作符代表最低优先级算符。
S2用来放输出的后缀式,操作数也是直接压入这里。
 
假设只包含加减乘除和括号,算法规则如下:
从左到右依次读取中缀表达式 ,比如“1+2*3+(4+5)*6”,先弹出“1”,最后到“6”
1.读到操作数,直接压入S2栈顶。
2.读到非括号操作符 则按照有限级操作
  如果操作符比S1栈顶操作符优先级高,则直接压入栈顶。(这里可以解释为什么要放个#在栈底,因为第一个操作符可以和#比较,程序比较归一化)
  如果操作符比S1栈顶操作符优先级不高,则弹出S1栈顶并压入S2,直到当前操作符高于S1栈顶,然后将当前操作符压入S1栈顶。
3.读到(,直接压入S1栈顶。
4.读到),则弹出离S1栈顶最近的(到栈顶间的所有操作符压入S2,之后弹出该(。
5.当中缀表达式读取完毕,将S1内剩余的操作符逐个弹出并压入S2
6.S2中即为后缀表达式(从底到顶,如果S2出栈得反转下)
 
 
a1. 1+2*3+(4+5)*6
S1.#,
S2.
 
S1.#,+
S2.1,2
 
S1.#,+,*
S2.1,2,3
 
S1.#,+,
S2.1,2,3,*,+
 
S1.#,+,(,
S2.1,2,3,*,+
 
S1.#,+,(,+
S2.1,2,3,*,+,4,5
 
S1.#,+,
S2.1,2,3,*,+,4,5,+
 
S1.#,+,*
S2.1,2,3,*,+,4,5,+6
 
S1.#
S2.1,2,3,*,+,4,5,+,6,*,+ (end)
 
b1. ((1+2)*3+4)*5+6 
S1.#,(,(+
S2.1,2
 
S1.#,(
S2.1,2,+
 
S1.#,(,*
S2.1,2,+,3
 
S1.#,(,+
S2.1,2,+,3,*,4
 
S1.#
S2.1,2,+,3,*,4,+,
 
S1.#,*
S2.1,2,+,3,*,4,+,5,
 
S1.#,+
S2.1,2,+,3,*,4,+,5,*,6
 
S1.#
S2.1,2,+,3,*,4,+,5,*,6,+ (end)

逆波兰算法

标签:

原文地址:http://www.cnblogs.com/uncleqiang/p/4892739.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!