1. 栈的定义
栈(stack)是限定在仅在表尾进行插入和删除操作的线性表。我们把允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。栈又成为后进先出的线性表。
栈的插入操作,叫作进栈,也称压栈、入栈;栈的删除操作,叫作出栈,也有的见弹栈。
2. 栈的抽象数据类型
对于栈来说,理论上线性表的操作特性它都具备,可由于它的特殊性,所以针对它的操作上会有些变化。特别是插入和删除操作,我们改名为push和pop,进栈和出栈。
3. 栈的顺序存储结构及实现
栈的顺序存储结构其实也是线性表顺序存储的简化,简称顺序栈。用数组来说,我们把下标为0的一段端作为栈底,因为首元素都存在栈底,变化最小。我们对顺序栈最基本的两个操作就是进栈操作和出栈操作。
4. 两栈的共享空间
顺序栈非常方便,因为它只准栈顶进出元素,所以不存在线性表插入和删除时需要移动元素的问题。但它有一个很大的缺陷,就是必须实现确定数组存储空间大小,一旦不够用,我们就需要编程手段来扩展数组的容量。但对于两个相同类型的栈,我们可以做到最大限度地利用其事先开辟的存储空间来进行操作。
做法如下:数组有两个端点,两个站有两个底栈,让一个栈的栈底为数组的始端,即下标为0处,另一个个栈为栈的末端,即下标为数组长度n - 1处。这样,两个栈如果增加元素,就是两端点向中间延伸。
5. 栈的链式存储结构及实现
栈的链式存储结构简称为链栈。我们把栈顶放在单链的头部,对于链栈来说,是不需要头结点的。
链栈中的基础操作也是进栈和出栈操作。
6. 顺序栈和链栈
两个栈在时间复杂度上是一样的,均为O(1)。对于空间性能,顺序栈需要事先确定一个固定的长度,可能会存在内存空间浪费的问题,但它的优势是存取时定位很方便,而链栈则要求每个元素独有指针域,这同时也增加例一些内存开销,但对栈的长度没有限制。
关于两者之间的选择,如果栈的使用过程中元素变化不可预料,有时很小,有时很大,那么最好用链栈,反之,如果它的变化在可控范围之内,建议使用顺序栈会好一些。
7. 栈的作用
栈的引入简化例程序设计的问题,划分了不同关注层次,是的思考范围缩小,更加聚焦于我们要解决的问题核心。栈有一个很重要的应用:在程序语言中实现例递归。
8. 递归
我们把一个直接调用自己或通过一系列的调用语句间接地调用自己的函数,称为递归函数。每个递归定义必须至少有一个条件,满足时递归不再进行,即不再引用自身而是返回值退出。
9. 递归和迭代的区别
迭代使用的是循环结构,递归使用的是选择结构。递归能使程序的结构更清晰、更简洁、更让人理解,从而减少读懂代码的时间。但大量的递归调用会建立函数的副本,会耗费大量的时间和内存。迭代则不需要反复调用函数和占用额外的内存。因此我么应该视不同的情况选择不同的代码实现方式。
10. 递归和栈的关系
递归过程退回的顺序是它前行顺序的逆序。在退回过程中,可能要执行某些动作,包括回复在前行过程中存储起来的某些数据。这种存储某些数据,并在后面又以存储的逆序恢复这些数据,以提供之后使用的需求,显然很符合栈这样的数据结构。zhon