当前位置: 首页 > news >正文

数据结构 --- 队列

队列 --- Queue

  • 前言
  • 一、整体结构
  • 二、相关方法
    • 1.初始化
    • 2.销毁
    • 3.入队 - - - 队尾插插入数据
    • 4.出队 - - - 队头删除数据
    • 5.获取队头 / 队尾元素
    • 6.判空
    • 7.获取队列有效元素个数

前言

队列是一种特殊的线性表,其特性是先进先出,只能在队尾入数据,在队头出数据,本次实现使用链表结构实现队列,对比数组实现有下列优点:
在这里插入图片描述

尽管现在来看两者的时间复杂度是差不多的,但是对于链表来说,我们只需要再定义一个尾节点来表示队尾即可将入队操作的时间复杂度优化为O(1),而数组的出队操作是无法优化时间复杂度的,所以综上所述本次实现选择链表结构实现队列。故而逻辑结构上是线性的,物理结构上不一定是线性的
本次实现使用C语言实现

一、整体结构

本次实现队列底层结构是链表,所以说有一个节点结构类型,并且队列操作数据只有队头和队尾位置可以操作,所以将其抽离出来,这就是队列的结构。

节点的结构:

typedef int QDataType;
// 队列的节点结构
typedef struct QueueNode
{QDataType data;          // 数据域struct QueueNode* next;  // 指针域
}QueueNode;

队列的结构:

// 队列的结构
typedef struct Queue
{QueueNode* phead;     // 队头QueueNode* ptail;     // 队尾// int size;          // 有效数据个数
}Queue;

二、相关方法

1.初始化

初始化即将队列phead和ptail置为空即可。

// 初始化
void QueueInit(Queue* pq)
{// pq不能为空assert(pq);// 初始化成空pq->phead = pq->ptail = NULL;// pq->size = 0;
}

创建一个空队列q1并初始化它,
监视窗口演示:
在这里插入图片描述

2.销毁

常见的标记销毁位置起始的节点,并记录此位置的下一个节点,之后循环销毁节点,完成后将phead和ptail置为NULL。

// 销毁
void QueueDestroy(Queue* pq)
{assert(pq);// 标记队头QueueNode* pcur = pq->phead;// 销毁节点while (pcur){// 记录pcur的下一个节点QueueNode* pnext = pcur->next;free(pcur);pcur = pnext;}// 销毁完成后phead和ptail置为NULLpq->phead = pq->ptail = NULL;// pq->size =0;
}

3.入队 - - - 队尾插插入数据

入队两步骤:
1)申请新节点,动态开辟(malloc)一个节点大小的内存空间,更新数据域为入队元素x,再将指针域置为NULL。
2)判断队列是否有元素,若有元素则直接在队尾ptail后面插入数据,并更新队尾指针指向;若没有元素,则新插入的节点newnode既是队头phead也是队尾ptail。

// 入队 --- 队尾入
void QueuePush(Queue* pq, QDataType x)
{assert(pq);// 申请新节点QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));if (newnode == NULL){perror("malloc");exit(1);}newnode->data = x;newnode->next = NULL;// 当队列为空时if (pq->phead == NULL){// 新节点就是队头和队尾pq->phead = pq->ptail = newnode;}// 当队列不为空时else{// 队尾入队列pq->ptail->next = newnode;// 移动队尾指针pq->ptail = pq->ptail->next;}// pq->size++;
}

向初始化完成后的队列q1入队三个数据:10,20,30
监视窗口演示:
在这里插入图片描述

4.出队 - - - 队头删除数据

出队两步骤:
1)判断队列是否是非空状态,只有有元素才可以出队。
2)判断队列的节点个数,当只有一个节点时,销毁此节点并将phead和ptail置为NULL;当有多个节点时,也是销毁此节点,并更新队头指针。

// 出队 --- 队头出
void QueuePop(Queue* pq)
{// 队列非空才可以出队assert(!QueueEmpty(pq));// 当队列只有一个节点if (pq->phead == pq->ptail){free(pq->phead);pq->phead = pq->ptail = NULL;}// 当队列有多个节点时else{// 标记队头的下一个节点QueueNode* pnext = pq->phead->next;free(pq->phead);// 移动队头至下一个节点pq->phead = pnext;}//pq->size--;
}

向入队完成后的队列q1出队前两个数据:10,20
监视窗口演示:
在这里插入图片描述

5.获取队头 / 队尾元素

获取两者的元素各自访问队头队尾指针的数据域即可,前提是队列非空。

获取队头元素:

// 获取队头元素
QDataType QueueFront(Queue* pq)
{// 队列非空才可以获取assert(!QueueEmpty(pq));return pq->phead->data;
}

获取队尾元素:

// 获取队尾元素
QDataType QueueBack(Queue* pq)
{// 队列非空才可以获取assert(!QueueEmpty(pq));return pq->ptail->data;
}

6.判空

队列为空的条件是队头指针或者队尾指针等于NULL。

// 判空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->phead == NULL;
}

7.获取队列有效元素个数

有两种方法:
1)遍历队列,定义一个计数器size,每访问一个节点计数器加一。
2)在队列属性里多增加一个size属性,直接返回size即可,增加这一个属性之后,初始化,入队,出队,销毁这种需要改变size大小的方法也需要对size进行操作。

// 获取队列有效元素个数
int Queuesize(Queue* pq)
{// 方法一:遍历,统计// 适用于非频繁访问有效数据个数的场景 : O(N)// 标记队头QueueNode* pcur = pq->phead;int size = 0;while (pcur){size++;pcur = pcur->next;}return size;// 方法二:给队列增加一个size属性// 适用于频繁访问有效数据个数的场景 :O(1)//return pq->size;
}
http://www.dtcms.com/a/273021.html

相关文章:

  • 10.Docker安装mysql
  • chatgpt是怎么诞生的,详解GPT1到GPT4的演化之路及相关背景知识
  • dexie 前端数据库封装
  • 使用快捷键迅速校准多个通道 | IPEmotion
  • 软件技术:柯里化
  • 《PyQt6-3D应用开发技术文档》
  • 仿豆包智能输入框实现
  • python基础25_某大网校(下)处理json数据以及保存题库
  • 安全访问云端内部应用:用frp的stcp功能解决SSH转发的痛点
  • Linux驱动开发(platform 设备驱动)
  • 老题新解|矩阵转置
  • AI驱动的业务系统智能化转型:从非结构化到结构化的智能转换
  • 【STM32 学习笔记】FLASH闪存
  • pytorch学习-12循环神经网络(基础篇)
  • 机器视觉之激光码检测系统
  • 【世纪龙科技】学测-汽车信息化综合实训考核平台(机电方向)
  • 数字孪生系统如何助力汽车零部件企业实现虚拟智控
  • RedisJSON 内存占用剖析与调优
  • Lua嵌入式爬虫实现步骤
  • 【Linux系统】冯诺依曼体系结构 | 初识操作系统
  • 生产者、消费者问题(C语言、POSIX)
  • 测试覆盖标准-条件覆盖-短路求值
  • 全新开源AI知识库系统!PandaWiki一键构建智能文档,支持AI问答、创作与搜索!
  • [特殊字符] 05_Jenkins 部署前端项目实现自动化部署
  • rv1106使用笔记
  • 【RL-VLM-F】算法框架图绘图学习笔记
  • ubuntu server配置静态IP
  • ​​​​​​​微软PowerBI PL-300认证考试报名入口及费用
  • 【PTA数据结构 | C语言版】顺序队列的3个操作
  • 完美卸载 Ubuntu 双系统:从规划到实施的完整指南