如果把操作限制于一个表,那么这些操作会执行的很快,然而,令人惊奇的是,这些少量的操作非常强大和重要,这就表明表、栈和队列的应用十分广泛。这里笔者谈谈栈的一个应用,在日后的学习总结中再慢慢将其余的应用展示说明。
栈的应用有很多,例如编译器检查程序的语法错误,但是常常由于缺少一个符号引起编译器列出上百行的诊断,而真正的错误并没有找出,在这种情况下一个有用的工具就是检验是否每件事情都能成对出现的一个程序,于是每一个右花括号、右方括号及右圆括号必然对应其相应的左括号,这个简单的算法用到一个栈,叙述如下:做一个空栈,读入字符直到文件尾。如果字符是一个开放符号,则将其推入栈中;如果字符是一个封闭符号,则当栈空时报错,否则,将栈元素弹出,如果弹出的符号不是对应的开放符号,则报错,在文件尾,如果栈非空则报错。
此外,栈还可以应用在其他方面。假设我们有一个便携计算器并想要计算含有四则混合运算的计算式,在现在的科学计算器上我们可以轻松的得到答案,但是现在我们考虑如何通过对一个简易计算器编程实现这样的功能,这样的话我们需要在按下“=”键之前计算器能记住中间结果。例如在计算4*2+6+7*2=?时,计算顺序可以是将4和2相乘结果存入A1,A1与6相加存入A1,计算7和2相乘存入A2,最后将A1和A2相加存入A1并输出,这种操作顺序书写如下:
4 2 * 6 + 7 2 * +
这种记法叫做后缀或逆波兰记法,其求值过程恰好就是上面描述的过程。计算这个问题最容易的方法是使用一个栈:当见到一个数时就把他推入栈中,在遇到一个运算符时就作用于该栈弹出的两个数上,将所得的结果放入栈中。
对于上面的式子的计算过程如下:
前两个字符放入栈中,此时栈变成
4 2 <- top of stack
下面一个读到一个“*”号,所以把2和4从栈中取出,并把2*4的结果放入栈,此时栈变成 [ 8 <- top of stack ]
接着将6放入栈中
8 6 <- top of stack
读到“+”号,取出8和6,并将8+6的结果放入栈中
14 <- top of stack
将7和2读入栈内
14 7 2 <- top of stack
读到“*”号,取出7和2,并将7*2结果放入栈中
14 14 <- top of stack
读到“+”号,取出14和14,并将14+14结果放入栈中
28 <- top of stack
最后读完,将栈中的元素28取出即为结果。
对于4*2+6+7*2,我们首先读到4,将其放到输出中,然后“*”被读到,将其放入栈中
[ * <- top of stack ],output [ 4 ]
下面读到2,将其放到输出中,接着读到“+”,其优先级比栈顶的“*”低,弹出“*”到输出中,将“+”放入栈中,后面的6也放到输出中
[ + <- top of stack ],output [ 4 2 * 6 ]
接着读到“+”,和栈中“+”优先级相同,将栈中“+”放入输出中,将读到的“+”放入栈中,后面的7放到输出中
[ + <- top of stack ],output [ 4 2 * 6 +7 ]
下面读到的“*”优先级比栈中“+”高,将其放入栈中,后面的2放到输出中
[ + * <- top of stack ],output [ 4 2 * 6 + 7 2 ]
最后输入的内容读完,依次将栈中的符号弹出到输出中,直到栈为空,得到的就是我们想要的后缀表达式
[ <- top of stack ],output [ 4 2 * 6 + 7 2 * + ]
通过将标准表达式转换为后缀表达式,再由后缀表达式计算原式的答案,我们就可以用简易的计算器完成这样混合运算,经过一些规则的设置,可以将这种情形应用到更广的地方。