栈在表达式求值中的应用

1,235 阅读2分钟

表达式求值

理解表达式的三种表示方法:前缀表达式、中缀表达式、后缀表达式

中缀表达式

首先,我们来说中缀表达式,因为我们平时书写的表达式的方式使用的就是这种方式,举例如下:

1 + 2 * 2 / 2 - 3

运算符都在数字中间。

可是,对于计算机而言,这种表示方法, 不容易计算,因为:当计算机从左往右扫描表达式时,总是需要看后面的运算符的优先级是否高于前面的运算符,然后才能决定是否能计算。通过这句话的描述,我想,我们很容易使用栈来解决,总是用栈去保存前面扫描到的运算符。细节不多说,可以参考LeetCode上这一题:Basic Calculator II

后缀表达式

当理解的中缀表达式,我们也就很容易理解后缀表达式。后缀表达式,就是将运算符放在数字的后面。咱们将上面的中缀表达式转为后缀表达式看看:

1 2 2 * 2 / + 3 -

计算机在处理后缀表达式时,那是相当简单。当计算机从左边往右扫描表达式时,每遇到一个运算符,便提出两个操作数,然后,进行计算。拿上面的表达式来说:

计算机从左往右扫描表达式,遇到数字时,直接将其保存栈中,遇到的第一个运算符是*,即乘法,然后从栈中弹出第而和第一个操作数(注意:由于栈是先进后出,所以,第一次弹出的第二个操作数,对于加法和乘法无所谓,但是对于减法和除法,则要小心),计算完成后,将结果在压入栈中。

伪代码如下:

int sec = stack.pop();
int first = stack.pop();
stack.push(first * sec);

对于后缀表达式,LeetCode也有一题与之对应:Evaluate Reverse Polish Notation

顺便提一下,后缀表达式,又叫逆波兰式,英文叫:Reverse Polish Notation

前缀表达式

理解上面两种表达式后,对于前缀表达式,就简单多了。这里就不过多描述。如有兴趣,可以凭着类比的方法,将上面的表达式转为前缀表达式,并尝试思考下,计算机处理起来,是否也很简单?

参考

  1. 《数据结构(C语言版)》机械工业出版社出版,Ellis Horowitz等人著作
  2. 《算法》Robert Sedgewick