栈和队列实现的思路和代码

源代码挂在最后的总结处
语言还是C

第一节----栈

什么是栈

接下来我们要学习的两个数据结和前面的链表相比要简单很多了,我们主要讨论一下他们的主要性质和实现思路。

栈的定义:
栈是限定仅在一端进行插入和删除的线性表
注意两个点,仅在一端和线性表

首先我们知道栈也是一种线性表,回想一下我们之前学过的顺序表和链表,这两位也是线性表,线性表无非就两种存储结构,顺序的和链式的,根据各自的优缺点,在前面的顺序表我们使用的顺序存储结构,链表使用的是链式的存储结构。那么我们来讨论一下栈使用什么存储结构比较好?

采用哪种存储结构,要根据栈的插入和删除特点来决定,我们把插入数据的一端叫做栈顶,另一端叫做栈底,并且后进如的数据先出,先进入的数据后出(如图)
在这里插入图片描述
基于这种特性刚好符合我们的数组的特性,如果采用链表的话,时间复杂度相比较于数组会有所提高。

确定了存储结构和栈的先进后出,后进先出的性质之后,下面我们就来开始写代码,实现栈。

实现栈的基本思路

使用顺序的存储结构实现栈和顺序表的实现的代码差不多,所以我们还是除了数组之外给出一个pop变量表示栈中元素的个数,在插入时pop++;,删除时pop–(和前面顺序表的size是一个道理),然后capacity表示容量的大小,当然在容量足的时候也要实现相应的扩容。

对于更具体的插入和删除等等接口函数的实现思路,我们放在各个函数的部分去介绍。

各个接口函数的实现

在这里插入图片描述

初始化栈

初始化的函数接口和我们的顺序表的差不多,我这里先给出了,初始的容量的大小,后续可以再扩容。当然你也可以写成静态(即容量的大小是固定的,容量满了以后不能进行扩容)。
在这里插入图片描述

销毁栈

因为使用的是数组,所以销毁就会容易很多,不必像链表那样一个一个的释放空间。
直接释放整个数组就好了。
在这里插入图片描述

压栈

压栈就是向栈中添加数据元素,有时也叫入栈。
在压栈的时候,我们就要考虑一个问题了,我们前面初始化的时候给的容量大小是4,那么当容量满的时候就要进行扩容的操作,所以我们在正在压榨之前要进行容量的检查,这一点也是和我们前面的顺序表没啥区别的。

这里我在扩容的时候,扩的是原容量大小的二倍。
在这里插入图片描述

出栈

出栈就是从栈中拿出一个数据元素,前面我们已经分析过,栈中数据的存和取都是在一端进行的,那么根据栈的特性,我们直接让pop–即可,这样我们在下一次进行入栈的时候,就能将原数据直接覆盖掉了。
在这里插入图片描述
值得注意的一点是,如果栈已经空了的话(也就是pop为0),这时候就不能再进行出栈的操作了,所以进行断言或者其他的操作也行。

返回栈顶元素

在这里插入图片描述
因为我们的pop表示的是栈中数据的个数,也是下一个数据要插入的位置,所以在返回栈顶数据时要pop-1。
同时栈为空的时候,也是不能进行返回栈顶元素的操作的(都没数据了,还返回个屁)。

栈的判空

栈的判空更简单了。
在这里插入图片描述

栈的大小

根据我们前面的分析,栈的大小也就是pop的大小
在这里插入图片描述
栈的讲解到此就结束啦!

第二节----队列

什么是队列

对列可是说是正好跟栈是反着来的。

队列的定义:
对列是在一端进行插入,另一端进行删除的线性表结构
它和栈的相同点都是线性表,所以我们待会肯定还是要讨论一下队列使用那种存储结构
不同点是,队列的是一端进行插入一端进行删除的线性表,而栈是限定在一端的。

那么我们就先来分析一下,队列使用链式的存储结构好还是使用顺序的存储结构好。

还是一样的,根据它的性质来,我们如果选用顺序表的话,无论是在哪一头进行删除或者插入的操作,都会移动大量的元素,如下图:
在这里插入图片描述
可以看到我们要是想删除1的话,那么后面的数据都需要进行前移一位,根据我们前面所将的链表的知识点来看,正好能避免这一点,所以链表的存储结构更加的适合队列这一种数据结构。

而且单链表就足以满足我们给队列的操作了。

实现队列的基本思路

首先声明一点:我们这里在实现对列的时候,不使用头结点。

在跟之前实现单链表所不同的一点是,我们增加两个指针来指向头和尾,这样我们在后续的接口函数时会方便很多,也会降低时间复杂度。
在这里插入图片描述

各个接口函数的实现

这里是我们接下来要实现的各个接口函数
在这里插入图片描述

队列的初始化

因为我们后面是要通过对head和tail两个指针来控制函数的一系列操作的,所以函数的参数的是Queue*
在这里插入图片描述

队列的销毁

队列的销毁也可以和顺序存储结构的销毁做个对照,顺序存储结构因为是一段连续的存储空间,所以我们可以直接释放掉一整个空间,但是链式的就不行,需要一个一个释放。
在这里插入图片描述

队列的插入

因为我没有使用头结点,所以要考虑一下是否是第一次插入,如果是的话,就将新的结点地址赋值给head和tail即可,如果不是的话,就需要用tail来链接起来。
在这里插入图片描述
size记得++;

队列的删除

删除的时候需要考虑的一种情况是,队列如果为空的话就不能再进行删除了,我这里是用一个函数来判断是否为空,这个函数在后面会实现的,大家也可以换一种方式来判断。

size减减之后,要记得释放掉删除的空间。
在这里插入图片描述

返回队头元素和队尾元素

队头元素和队尾元素:
在这里插入图片描述

因为我们有head和tail指针,所以在返回队头的元素和队尾元素的时候,就很好操作了。
队头元素:
在这里插入图片描述
队尾元素:
在这里插入图片描述

队列的判空

当headtail空的时候即是空,这里将head换成tail或者写成headtail空都是可以的。
在这里插入图片描述

队列的大小

在这里插入图片描述

总结

源代码地址:
队列

相信大家只要学习完前面的顺序表和链表,这两种结构对大家来说就没什么难度,下面给出两道题目,帮助大家加深给栈和队列的理解和认识
用栈实现队列
用队列实现栈

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南山忆874

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值