数据结构-队列、栈

功能受限的表结构

一、栈和队列介绍

  • 栈和队列是两种重要的线性结构,从数据结构角度,他们都是线性表,特殊点在于它们的操作被限制,也就是所谓的功能受限,统称功能受限的线性表
  • 从数据类型角度,它们也可以是看成处理、管理数据的一种规则

二、栈结构

  • 栈(stack)是限定在表尾进行数据的插入、删除等操作的线性表(只允许操作一个端口的数据)

  • 表尾称为栈顶,表头称为栈底 ,当没有元素的空表称为空栈,当元素的数量到达栈的容量时称为满栈 ,添加数据到栈顶中的动作称为入栈压栈,把数据从栈顶中拿出的动作称为出栈弹栈,正因为这个数据的添加、删除的规则,所以栈中元素满足先进后出,简称FILO表LIFO表

栈结构可以具备的功能

  • 创建
  • 销毁
  • 是否满栈
  • 是否空栈
  • 入栈
  • 出栈
  • 查看栈顶元素
  • 查看元素数量

注意:只有顺序栈才有需要判断栈是否满

1、栈结构的顺序实现

设计顺序栈结构

typedef struct ArrayStack {
    TYPE* ptr;      //  存储栈元素的内存首地址
    size_t cap;     //  栈的容量
    size_t top;     //  栈顶的位置 
} ArrayStack;

代码实现

2、栈结构的链式实现

#define TYPE int
typedef struct ListNode {
    TYPE data;
    struct ListNode* next;
} ListNode;

//  链式栈结构
typedef struct ListStack {
    ListNode* top;      // 栈顶指针 指向栈顶节点
    size_t size;        // 节点数量
} ListStack;

代码实现

3、栈的应用

  • 内存管理,例如栈内存,之所以叫栈内存因为它遵循栈的先进后出原则,函数调用、函数参数的传参、定义,先把数据入栈,等结束时,逆序出栈,函数的调用、结束跳转也是遵循栈结构原则
  • 特殊的算法:算术表达式的转换(中缀表达式转后缀表达) 、进制转换、迷宫算法

三、队列结构

1、队列介绍

  • 与栈结构相似的是,也只允许在端口处进行添加、删除操作,但是有两个端口,一个负责添加数据,称为入队 ,该端口称为队尾,另一个端口只负责删除数据,称为出队,该端口称为队头,属于一种先进先出结构,称为FIFO

2、队列所具备的功能

  • 创建队列
  • 销毁队列
  • 判断队空
  • 判断队满 (只有顺序存储时才有)
  • 入队
  • 出队
  • 查看队头元素
  • 查看队尾元素
  • 队列元素数量

3、队列的链式实现

#define TYPE int

typedef struct ListNode {
    TYPE data;
    struct ListNode* next;
} ListNode;

//  设计链式队列结构
typedef struct ListQueue {
    ListNode* front;    //  队头
    ListNode* rear;     //  队尾
    size_t size;        //  节点数量
} ListQueue;

代码实现

4、队列的顺序实现

  • 顺序队列的队尾下标rear会随着入队而增大rear+1,队头下标front会随着出队增大front+1,因为是顺序结构,就有随着入队和出队的进行,可能超出有效的下标范围,如果不进行处理,那么队列无法重复使用。
  • 为了避免这种情况,当队尾、队头下标达到存储空间的末尾时,要想办法让它们回到内存的开头位置,相当于把内存想象成一个环形,从而可以循环使用队列,这样的队列称为循环队列
    • 因此当队尾、队头下标增加时,都要对队列的容量求余
    • rear = (rear + 1) % cap
    • front = (front + 1) % cap
带计数器版本的循环队列
  • 很直接地解决了元素数量的问题
  • 可以直接解决队空、队满的判断矛盾问题
  • 但是在队列结构中会多增加一个数据项,并且每次入队、出队操作都要对其进行修改
typedef struct ArrayQueue {
    TYPE* ptr;      //  存储元素的内存首地址
    size_t cap;     //  容量
    size_t cnt;     //  元素个数  计数器
    int front;      //  队头下标
    int rear;       //  队尾下标
} ArrayQueue;

代码实现

不带计数器的版本

判断队空、队满状态

假如把front初值设置0,rear初值设置0,当开始队空状态时front == rear,不停入队rear不停地加1,当队满时,rear == front,导致无法判断队空还是队满
解决方法是:多申请一个存储元素的内存,这样会让存储元素的内存中总有一个元素内存不使用,但是队满的条件就变成了 front == (rear + 1)% cap
注意cap是真实的容量 但是调用者能使用的容量是cap - 1
而队空条件依然是:front == rear 这样就可以不同计数器也能判断队空队满

计算数量(rear - front + cap) % cap

查看队尾元素ptr [(rear - 1 + cap)% cap]

代码实现

5、队列的应用

  • 一般应用于业务处理,例如:银行叫号系统、购票系统等
  • 树的层序遍历
  • 图的广度优先遍历BFS
  • 线程池、数据池
posted @   sleeeeeping  阅读(28)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
  1. 1 吹梦到西洲 恋恋故人难,黄诗扶,妖扬
  2. 2 敢归云间宿 三无Marblue
敢归云间宿 - 三无Marblue
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

敢归云间宿 - 三无Marblue

词:怀袖

曲:KBShinya

编曲:向往

策划:杨颜

监制:似雨若离RainJaded/杨颜

吉他:大牛

混音:三无Marblue

和声:雾敛

母带:张锦亮

映像:似雨若离RainJaded

美术:阿尼鸭Any-a/乙配/雨谷/今风/米可/Eluan

题字:长安

酒 泼去群山眉头

酒 泼去群山眉头

月 悬在人世沧流

空杯如行舟 浪荡醉梦里走

心 生自混沌尽头

心 生自混沌尽头

对 天地自斟自酬

诗随我 遍历春秋

行流水 走笔形生意动

见珠玉 淙淙落纸成诵

拾得浮名有几声 云深处 却空空

耳畔丝竹 清商如雾

谈笑间 却是心兵穷途

飞觞醉月无归宿 便是孤独

不如就化身为风

卷狂沙 侵天幕

吹醒那 泉下望乡 的战骨

昨日边关犹灯火

眼前血海翻覆

千万人跌落青史 隔世号呼

于是沸血重剑共赴

斩以雷霆之怒

肩背相抵破阵开路

万古同歌哭

纵他春风不度 悲欢蚀骨

此去宁作吾

挣过命途 才敢写荣枯

望 云际群龙回首

望 云际群龙回首

任 飘蓬争逐身后

叹冥顽之俦 好景尽付恩仇

收 江声随酒入喉

收 江声随酒入喉

来 提笔御风同游

不觉已 换了春秋

真亦假 泼墨腾烟沉陆

有还无 蝶影纷堕幻目

我与天地周旋久

写尽梦 便成梦

夜雨浇熄 往事残烛

生死间 谁尽兴谁辜负

管他醒来归何处 心生万物

也曾对电光火雨

抛酒樽 镇天枢

护住了 人间多少 朝与暮

烧尽了阴云冥府

烧尽了阴云冥府

且看星斗尽出

浩荡荡尘埃野马 忘怀命数

于是信步鸿蒙之轻

也领苍生之重

与诗与剑颠倒与共

沉眠斜阳中

纵他世事汹涌 万类争渡

此去宁作吾

醉得糊涂 才梦得清楚

潮水 带着叹息轻抚

潮水 带着叹息轻抚

像光阴 漫过大地上幽微草木

有情世 见众生明灭往复

天生自在 何必回顾

晦暗中双掌一拊

立此身 照前路

与某个 阔别的我 决胜负

渺渺兮身外无物

无喜无悲无怖

不过是大梦一场 各自沉浮

于是纵横万相穷通

也守心底灵通

合眼识得星沉地动

也岿然不动

敢令岁月乌有 逍遥长驻

敢归云间宿

遥祝远行人 有道不孤

点击右上角即可分享
微信分享提示