栈是一种特殊的线性表,栈限定仅在表尾进行插入或删除的操作。因此,对栈来说,表尾端有其特殊含义,成为栈顶(top),相应的,表头端称为栈底(bottom)。不含元素的空表称为空栈。栈又称为后进先出(last in first out)的线性表。
一、(Java)栈的实现
由于栈是一个表,因此任何实现表的方法都能实现栈。显然ArrayList和LinkedList都支持栈操作;99%的时间它们都是最合理的选择。因为栈操作是常数时间操作,所以,除非在非常独特的环境下,这是不可能产生任何明显的改进的。
对于这些特殊的时机,有两个流行的实现方法:
- 链式结构
- 数组
1)栈的链表实现
通过在表的顶端插入来实现push,通过删除表顶端的元素实现pop。top操作至少考察表顶元素并返回它的值。有时pop和top操作合二为一。
2)栈的数组实现
这种实现方式避免了链而且可能是更流行的方式。由于模仿ArrayList的add操作,因此相应的实现方法更简单。
与每个栈相关联的操作是theArray和topOfStack
- 对于空栈通过-1初始化
- 将某个元素x压栈,使用topOfStack增1然后theArray[topOfStack] = x
- 将某个元素x弹栈,设置返回值为theArray[topOfStack]然后topOfStack-1
注意,这些操作不仅以常数时间运行(时间复杂度O(1)),而且是以非常快的常数时间。在某些机器上,若在带有自增和自减寻址的寄存器上操作,则(整数的)push和pop操作都可以写为一条机器指令。最现代化的计算机将栈操作作为它的指令系统的一部分,这个事实强化了这样一种观念,即栈很可能是计算机科学中在数组之后的最基本的数据结构。
关于栈的数组实现方式不再提供Java代码,可以参考栈(C语言实现)。
但要注意,Java中的数组经过了二次封装,并非是C语言实现中直接看到的样子。
二、(Java)栈的应用
- 平衡符号:最常见的操作是编译器检查语法错误的过程,通过前/中/后缀表达式的转换实现
- 方法调用:最常见于Java虚拟机的操作数栈