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


    源代码挂在最后的总结处
    语言还是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空都是可以的。
    在这里插入图片描述

    队列的大小

    在这里插入图片描述

    总结

    源代码地址:
    队列

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

  • 相关阅读:
    C#设计模式---工厂方法模式
    攻防演练第四年的一些碎碎念
    LeetCode 1470. 重新排列数组 / 654. 最大二叉树 / 998. 最大二叉树 II
    .NET 8 Video教程介绍(开篇)
    数据结构02:线性表 链表习题02[C++]
    MySQL:存储过程与存储引擎
    【自动注入·名称】autowireByName()详解
    构建动态交互式H5导航栏:滑动高亮、吸顶和锚点导航技巧详解
    绘制同心圆-第12届蓝桥杯Scratch省赛1真题第3题
    【FPGA】十进制计数器 | 实现 4-bit 2421 十进制计数器 | 有限状态机(FSM)
  • 原文地址:https://blog.csdn.net/Javaxaiobai/article/details/127836528