大话数据结构之栈与队列

栈(stack)是限定仅在表尾进行插入和删除操作的线性表。

栈的底层实现是线性表,在Java的表现形式是Stack类有一个List类型的实例变量

不含任何数据元素的栈称为空栈。栈又称为后进先出(LIFO)的线性表。

栈是一种特殊的线性表。它的特殊之处就在于限制了这个线性表的插入和删除位置,它始终只在栈顶进行。这也就使得:栈底是固定的,最先进栈的只能在栈底。

进栈出栈变化形式

最先进栈的元素,是不是只能最后一个出栈呢?
肯定不是。可以最先进栈,然后马上出栈。


举例来说,如果我们现在是有3个整形数字元素1、2、3依次进栈,会有哪些出栈次序呢?
321、123、213、132、231都是可行的
按理来说A33应该是6种次序,那有没有可能是312这样的次序出栈呢?
答案肯定是不会。因为3首先出栈,这表明1和2已经进栈了,且2一定是在1的上面,也更为接近栈顶。那么下一个出栈必须是2,整个出栈次序只可能是321。

栈的抽象数据类型(ADT)

栈是特殊的线性表,理论上线性表的操作特性它都具备,但栈在操作上会有些变化。特别是线性表插入(add)和删除(remove)操作,栈改名为push和pop,英文直译为压和弹。

在这里插入图片描述

栈的两种存储方式

由于线性表有顺序存储和链式存储,栈是线性表,所以有这两种存储方式。

栈的顺序存储结构

栈是线性表的特例,那么栈的顺序存储结构其实也是线性表顺序存储结构的简化,我们简称为顺序栈。

以顺序存储结构来讲,线性表是用数组来实现的,下标为0的一端作为栈底,另一端作为栈顶。

栈的链式存储结构

对于链栈来说,基本不存在栈满的情况,除非内存已经没有可以使用的空间。

两者比较

对比以下顺序栈与链栈,它们在时间复杂度上是一样的,均为O(1)。顺序在需事先确定固定的长度,优势是存取时定位很方便,链栈则是对于栈的长度无限制。若栈的使用过程中元素变化不可预料,那么最好是用链栈,反之建议使用顺序栈。

队列

队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

队列是一种先进先出(FIFO)的线性表。允许插入的一端称为队尾,允许删除的一端称为队头。LinkedList是队列的一个实现类。

以栈的结构来讲,栈顶是线性表的表尾,另一端称为栈底,不含任何数据元素的栈称为空栈。栈又称为后进先出(LIFO)的线性表。
在这里插入图片描述

队列的抽象数据类型(ADT)

队列是特殊的线性表,理论上线性表的操作特性它都具备,不同的就是插入数据只能在队尾进行,删除数据只能在队头进行。
在这里插入图片描述

队列的两种存储方式

队列的顺序存储结构及不足

入队列操作,其实就是在队尾即数组末尾追加一个元素,不需要移动任何元素,因此时间复杂度为O(1),如图。
在这里插入图片描述
与栈不同的是,队列元素的出列是在队头,即下标为0的位置,意味着剩下的所有元素都得向前移动,以保证队头即下标为0的位置不为空,此时时间复杂度为O(n),如图。
在这里插入图片描述
顺序存储结构改良版之循环队列
循环队列就是将队列存储空间的最后一个位置绕到第一个位置,形成逻辑上的环状空间,供队列循环使用。在循环队列结构中,当存储空间的最后一个位置已被使用而再要进入队运算时,只需要存储空间的第一个位置空闲,便可将元素加入到第一个位置,即将存储空间的第一个位置作为队尾。 [1] 循环队列可以更简单防止伪溢出的发生,但队列大小是固定的。

队列的链式存储结构

队列的链式存储结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列。
一种实现类就是LinkedList

循环队列与链队列的比较

从时间上,其实它们的基本操作都是常数时间,即都为O(1)的,不过循环队列是事先申请好空间,使用期间不释放。对于空间上来说,循环队列必须有一个固定的长度(ArrayList则可以扩容),所以就有了存储元素个数和空间浪费的问题。而链队列不存在这个问题,更为灵活。

总的来说,在可以确定队列长度最大值的情况下,建议用循环队列,如果你无法预估队列的长度时,则用链队列。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值