3 32+ 5 3* -
12 34 2- * 8 /
乍一看上面两个式子很奇怪,是吗?它们就是这里所要讲到的一种表达式的记法——逆波兰表达式。
现在,准备一个很窄的圆筒,筒是有底的,像一个细长的杯子,粗细刚好和一枚硬币相当。再做几个和硬币一样大的小圆纸片,在纸片上依次写上“3”“32”“+”“5”“3”“*”“-”,记住,每个纸片上要么只写一个数,要么只写一个运算符号,把它们按上面的顺序排好。好,现在仔细听我说,按顺序一个接一个地拿起小圆纸片,反复执行以下几个规则:
1. 如果你拿着的是一个数,不多说,直接把它放进圆筒;
2. 如果你拿着的是一个运算符号,不要把它放进去。先从圆筒里取出两个数(当然是先取最上而的啦,筒很细的),然后处这两个数作运算符号指定的运算,并把结果写在一张新的纸片上,然后放进筒里。比如你拿着的是“+”,你要依次取出“32”和“3”,让它们相加,得“35”,把“35”写在一张新纸片上(现在“34”和“12”可以扔掉了),并把这张新纸片放进圆筒。
当圆筒里只有一个数时,你就可以停下来了,我猜这个数是20,没错,这就是这个表达式的值!
我们刚才操作的,其实就是一个“栈”,栈是一种数据结构,具有一个性质——后进先出(LIFO——Last Input First Output),你已经深有体会了,就像一摞盘子,你只能从最上面的开始取,放的时候也只能放在最上面。放进去的动作叫做“入栈”,取出来叫做“弹出”。以后你就可以把栈想像成一摞盘子,或是上面说的小圆筒和小纸片,栈就是这么简单!
逆波兰表达式虽然看起来比较繁琐,其实在计算机中很有用。计算机可不知道先乘除后加减,先括号内后括号外,它要把你输入的式子变成逆波兰表达式,它就可以不断地执行上面两个规则,直至把结果算出来告诉你。现在你可以亲自在计算机上试试,试着编一个程序,让它读入一个逆波兰表达式,然后让它计算!
成功了吗?如果你回答“是”,你可以接着思考另一个问题,对于7个元素的序列1 2 3 4 5 6 7,通过一个栈的处理后(比如1 2 3入栈,3 2弹出,4入栈,4弹出……如此等等),能得到多少种不同的排列?能得到4 3 5 2 1 7 6吗?能得到3 2 4 5 7 1 6吗?