栈文档之栈
Posted 二木成林
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈文档之栈相关的知识,希望对你有一定的参考价值。
栈
定义
栈(Stack)是只允许在一端进行插入或删除操作的线性表(与队列相比而言,队列是允许在两端进行插入或删除操作的)。
栈只能在栈顶进行插入或删除。如图所示:
关于栈的一些概念:
- 栈顶:可以进行插入或删除的一端,不是固定的(每插入或删除一个元素栈顶都会变)。
- 栈底:不能进行插入或删除的另一端,固定的。
- 空栈:即不含任何元素的空线性表。
- 入栈:也称为压栈,即插入操作,将元素从栈顶压入,然后新插入的元素成为新的栈顶元素。
- 出栈:也称为弹栈,即删除操作,将元素从栈顶弹出,然后下一个元素成为新的栈顶元素。
由栈的定义就可以直到栈的主要特点是先进后出(FILO,First In Last Out),也可以称为后进先出。因为只允许从栈顶入栈,从栈顶出栈,所以后进来的元素在先进来的元素的上方,所以能够先出去。
例如,某个栈 S=(a1, a2, a3, a4, a5)
,其中 a1 是栈底元素,a5 是栈顶元素。由于栈只能在栈顶进行插入和删除操作,进栈次序依次为 a1, a2, a3, a4, a5
,出栈次序为 a5, a4, a3, a2, a1
。
基本操作
注:
- 栈的基本操作的名称各不相同,应该说数据结构中的基本操作名称在各大书籍或资料中不尽相同,但表达的意思是相通的。
- 下面的基本操作中
&
表示引用调用,这是C++
的语法,仅是抽象表示,不必在意。但在实际实现中C
语言采用的是双指针,而Java
采用的是对象和函数返回值。
无论是顺序栈还是链栈,它的基本操作如下:
init(&Stack)
:初始化一个空栈。isEmpty(Stack)
:判断栈是否为空。push(&Stack, ele)
:进栈,若栈未满,则将 ele 插入使之成为新栈顶。pop(&Stack, &ele)
:出栈,若栈非空,则弹出栈顶元素,并用 ele 返回。getTop(Stack, &ele)
:读取栈顶元素,但不出栈,若栈非空,则用 ele 返回栈顶元素。size(stack)
:获取栈中的元素个数。print(stack)
:从栈顶到栈底打印栈中所有元素。clear(&stack)
:清空栈。destroy(&stack)
:销毁栈。
存储结构
栈是一种操作受限的线性表,也有两种存储方式,顺序存储和链式存储。前者称为顺序栈,后者称为链栈。
顺序栈
采用顺序存储的栈称为顺序栈,它采用一组地址连续的存储单元存放自栈底到栈顶的数据元素,同时设定一个指针(top)指向当前栈顶元素的位置。通常采用数组来实现。
更多请参考:顺序栈。
链栈
采用链式存储的栈称为链栈。链栈的优点是便于多个栈共享存储空间和提高效率,且不存在栈满上溢的清空。通常采用单链表实现,并且规定所有操作都是在单链表的表头进行上的(因为头结点的 next
指针指向栈的栈顶结点)。
注:所谓的栈上溢,是只有在顺序栈才会发生的情况,因为顺序栈分配的空间是有限的,如果栈已满,再进行入栈操作时,就会产生上溢。而链栈是不会出现这种情况的,因为空间是动态分配的。
更多请参考:链栈
两种存储结构的比较
顺序栈的特性:
- 空间静态分配,最大空间容量有限制,会存在栈上溢的情况。
- 必须是一块连续的存储单元。
- 通常使用数组实现。
- 插入操作和删除操作很快,都是在栈顶操作。
链栈的特性:
- 空间动态分配,不需要考虑空间不够的情况,不存在栈上溢的情况。
- 可以是离散的存储单元,不要求连续。
- 通常使用单链表实现。
- 插入操作和删除操作很快,都是在栈顶操作。所以跟顺序栈相比,这个不是明显优势。
其他栈
共享栈
共享栈是顺序栈的变种。利用栈底位置相对不变的特性,可以让两个顺序栈共享一个一维数组空间,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延申,如图所示:
其中两个栈的栈顶指针都指向栈顶元素。top0=-1
时表示 0 号栈为空,top1=MAXSIZE
时表示 1 号栈为空(这是设定,因为栈顶指针存储的是下标,而 -1
和 MAXSIZE
都表示不合法的下标,所以用来指定初始栈空条件)。当两个栈顶指针相邻(即 top1 - top0 = 1
)时,判断栈满。
共享栈能够更加有效地利用存储空间,两个栈的空间相互调节,只会在整个存储空间被栈满时才会发生上溢,存取数据的时间复杂度仍为 O(1)
。
更多请参考:共享栈。
以上是关于栈文档之栈的主要内容,如果未能解决你的问题,请参考以下文章