队列的实现(c语言实现)

队列的定义

队列(Queue)是一种特殊的线性数据结构,它遵循先进先出(FIFO,First In First Out)的原则。这意味着最早被添加到队列中的元素将是最先被移除的元素。队列的主要操作包括入队(enqueue,在队列的尾部添加元素)和出队(dequeue,从队列的头部移除元素)。

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。

入队列:队列的插入操作叫做入队列,进行插入操作的一端称为队尾。

出队列:队列的删除操作叫做出队列,进行删除操作的一端称为队头。

队列的实现方式

队列的实现方式有多种,包括基于数组(或循环数组)的实现、基于链表的实现等。

基于数组(或循环数组)的队列实现

这种实现方式使用一个固定大小或循环使用的数组来存储队列中的元素。数组的一个端点被视作队列的头部(front),用于执行出队操作;另一个端点被视作队列的尾部(rear),用于执行入队操作。当队列满时,需要判断是否有空间可以循环利用(即队头元素是否已被移除)。

基于链表的队列实现

基于链表的实现使用链表数据结构来存储队列中的元素。链表的头部被视作队列的头部(front),用于执行出队操作;链表的尾部被视作队列的尾部(rear),用于执行入队操作。这种实现方式更加灵活,因为链表不需要预先分配固定大小的空间,而且可以动态地扩展和收缩。

无论是基于数组还是基于链表的实现,队列都保持了其先进先出的特性,使得它在处理需要按顺序处理的元素序列时非常有用。

初始化队列

首先我们需要创建一个结点类型,类型包含了该结点的数据和指向下一结点的指针。

typedef int QDataType;//队列中存储的元素类型(这里用整型举例)typedef struct QListNode
{struct QListNode* next;//指针域QDataType data;//数据域
}QListNode;

队列与普通链表又有所不同,普通链表只需要知道链表的头指针,而队列的信息包括了队头和队尾,所以我们需要再创建一个结构体用于存放队列的队头和队尾。

typedef struct Queue
{QListNode* head;//队头QListNode* tail;//队尾
}Queue;

队列的基本操作

我们可以先看下面这一系列操作

typedef char QDatatype;typedef struct QueueNode
{struct QueueNode* next;QDatatype data;
}QNode;typedef struct Queue
{QNode* head;QNode* tail;int size;
}Queue;void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq, QDatatype x);
void QueuePop(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
QDatatype QueueFront(Queue* pq);
QDatatype QueueBack(Queue* pq);

初始化队列

// 初始化队列函数  
void QueueInit(Queue* pq)  
{  // 使用断言确保传入的队列指针不为空  assert(pq);  // 将队列的头部和尾部指针都初始化为NULL  // 初始化时队列为空,没有节点  pq->head = pq->tail = NULL;  // 将队列的大小初始化为0  // 队列中尚未包含任何元素  pq->size = 0;  
}

在这个函数中,我们首先使用assert宏来检查传入的队列指针pq是否为空。如果pq为空,assert将触发一个运行时错误,这通常用于调试以确保程序在运行时不会因为无效的指针而崩溃。

然后,我们将队列的头部和尾部指针都初始化为NULL,因为队列在初始化时是空的,没有任何节点。

最后,我们将队列的大小size初始化为0,表示队列中还没有包含任何元素。

销毁队列

// 销毁队列函数  
void QueueDestroy(Queue* pq)  
{  // 使用断言确保传入的队列指针不为空  assert(pq);  // 初始化当前节点为队列的头部节点  QNode* cur = pq->head;  // 循环遍历队列中的每一个节点,直到没有节点为止  while (cur)  {  // 保存当前节点的下一个节点的指针  QNode* next = cur->next;  // 释放当前节点所占用的内存  free(cur);  // 将当前节点移动到下一个节点,继续释放内存  cur = next;  }  // 将队列的头部和尾部指针都设置为NULL  // 表示队列已经被销毁,不再包含任何节点  pq->head = pq->tail = NULL;  // 将队列的大小设置为0  // 表示队列中没有元素  pq->size = 0;  
}

这个函数负责销毁一个队列,释放队列中所有节点所占用的内存,并将队列的头部和尾部指针以及大小重置为初始状态。

入队

// 入队操作函数  
void QueuePush(Queue* pq, QDatatype x)  
{  // 为新节点分配内存  QNode* newnode = (QNode*)malloc(sizeof(QNode));  // 检查内存分配是否成功  if (newnode == NULL)  {  // 如果内存分配失败,打印错误信息并返回  perror("malloc fail");  return;  }  // 将数据x赋值给新节点的data成员  newnode->data = x;  // 初始化新节点的next指针为NULL  newnode->next = NULL;  // 如果队列为空(即头部和尾部指针都为NULL)  if (pq->head == NULL)  {  // 断言确保尾部指针也为NULL(这通常是正确的,但如果不是则会导致逻辑错误)  assert(pq->tail == NULL);  // 将新节点设置为队列的头部和尾部节点  pq->head = pq->tail = newnode;  }  else  {  // 如果队列不为空,将新节点添加到队列的尾部  // 将当前尾部节点的next指针指向新节点  pq->tail->next = newnode;  // 更新尾部指针,使其指向新节点  pq->tail = newnode;  }  // 队列中的元素数量加1  pq->size++;  
}

这个函数用于将一个元素x添加到队列的尾部。

出队

// 出队操作函数  
void QueuePop(Queue* pq)  
{  // 断言确保队列指针不为空  assert(pq);  // 断言确保队列不为空  assert(pq->head != NULL);  // 如果队列中只有一个节点  if (pq->head->next == NULL)  {  // 释放头节点占用的内存  free(pq->head);  // 将头部和尾部指针都设置为NULL,表示队列为空  pq->head = pq->tail = NULL;  }  else  {  // 否则,队列中有多个节点  // 保存头节点的下一个节点的指针  QNode* next = pq->head->next;  // 释放头节点占用的内存  free(pq->head);  // 将头部指针指向原来的第二个节点  pq->head = next;  }  // 队列中的元素数量减1  pq->size--;  
}

获取队列中元素数量

// 获取队列大小函数  
int QueueSize(Queue* pq)  
{  // 断言确保队列指针不为空  assert(pq);  // 返回队列中的元素数量  return pq->size;  
}

这个函数用于获取队列中的元素数量。

检查队列是否为空

// 检查队列是否为空函数  
bool QueueEmpty(Queue* pq)  
{  // 断言确保队列指针不为空  assert(pq);  // 如果队列的大小为0,则返回true,表示队列为空  // 否则返回false,表示队列不为空  return pq->size == 0;  
}

这个函数用于检查队列是否为空。它接受一个指向队列的指针pq作为参数,并使用断言来确保这个指针是有效的。然后,它比较队列的大小(size)是否等于0。如果等于0,说明队列中没有元素,函数返回true;否则,队列中有元素,函数返回false

获取队列头部元素

// 获取队列头部元素函数  
QDatatype QueueFront(Queue* pq)  
{  // 断言确保队列指针不为空  assert(pq);  // 断言确保队列不为空  assert(!QueueEmpty(pq));  // 返回队列头部节点的数据  return pq->head->data;  
}

获取队列尾部元素 

// 获取队列尾部元素函数  
QDatatype QueueBack(Queue* pq)  
{  // 断言确保队列指针不为空  assert(pq);  // 断言确保队列不为空  assert(!QueueEmpty(pq));  // 返回队列尾部节点的数据  return pq->tail->data;  
}

这个函数用于获取队列尾部元素的值。它接受一个指向队列的指针pq作为参数,并使用断言来确保队列指针有效且队列不为空。

队列的尾部元素是队列中最后一个被加入的元素。由于队列的尾部节点可以通过tail指针直接访问,因此这个函数直接返回队列尾部节点的data成员的值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/3412.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【错题集-编程题】数组中的最长连续子序列(排序 + 模拟)

牛客对应链接:数组中的最长连续子序列_牛客题霸_牛客网 (nowcoder.com) 一、分析题目 排序 模拟。 注意:值连续,位置可以不连续!小心处理数字相同的情况。 二、代码 //值得学习的代码 class Solution { public:int MLS(vecto…

数字藏品:重塑艺术与科技的新媒介

数字藏品,这个新兴的词汇,正在逐渐渗透到我们的日常生活中。它不仅是一种新的艺术表达方式,更是一种科技与艺术相结合的全新媒介。那么,数字藏品究竟是什么呢? 首先,我们需要明确一点,数字藏品并…

LeetCode53. 最大子数组和

LeetCode53. 最大子数组和 解题思路dp 代码 /* 数组长度n 9,连续的区间 那区间长度为1的区间数量是&#xff0c;9个 区间长度为2的区间数量是8个 区间长度为3的连续的区间数量为7个 .... 区间长度为9的区间数量为1个 */ class Solution { public:int maxSubArray(vector<…

游戏工作室为什么要使用海外住宅IP防封?

当谈到游戏工作室时&#xff0c;它们通常以多开游戏账号来获取收益为主要目标。这种商业模式在游戏产业中已经成为一个独特而且颇具潜力的领域。然而&#xff0c;随之而来的是防封问题&#xff0c;特别是当游戏工作室试图通过多开账号来赚取更多收益时。因此&#xff0c;我们有…

13(第十二章,元数据管理)

目录 概述 业务驱动因素 目标和原则 基本概念 元数据与数据 元数据的类型 业务元数据 技术元数据 操作元数据 元数据注册标准 元数据来源 元数据架构类型 集中式元数据架构 分布式元数据架构 混合式元数据架构 双向元数据架构 方法 数据血缘和影响分析 度量…

Java操作 elasticsearch 8.1,如何实现索引的重建?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

U盘无法正常格式化?教你一个强力的办法

前言 电脑格式化U盘或者移动硬盘的操作&#xff0c;相信各位小伙伴都是有一定经历的。 如果设备正常&#xff0c;那么进入到【此电脑】&#xff0c;在对应的分区点击【鼠标右键】-【格式化】就可以把对应的存储设备恢复到初始状态。 但凡事都会有例外&#xff0c;比如在格式化…

【openLooKeng-1.10.0集群环境安装部署】

openLooKeng-1.10.0集群环境安装部署 一、摘要二、正文1. 环境说明2. 集群拓扑图3. 安装过程(以root用户安装)3.1 在Coordinator和Worker两个节点都需要安装jdk1.8+3.2 在Coordinator上安装配置openLooKeng3.3 在Worker节点上进行配置openLooKeng3.4 在Coordinator节点上先启…

施耐德EOCR-2CT-300/5电流互感器 50HZ 5VA

EOCR主要产品有电子式电动机保护继电器&#xff0c;电子式过电流继电器&#xff0c;电子式欠电流继电器&#xff0c;电子式欠电压继电器&#xff0c;其它保护和监视装置&#xff0c;电流互感器。 施耐德EOCR-2CT-300/5电流互感器 EOCR-2CT系列型号&#xff1a; EOCR 2CT 100…

本地安装mysql并用python访问它

数据还是放在数据库中比较好&#xff0c;于是决定在本机安装个mysql服务。 环境&#xff1a;windows 10&#xff0c;python3.8.10 安装前首先要注意一点&#xff1a; 设置-系统-关于-设备&#xff08;电脑&#xff09;名称&#xff1a;为英文 一、进入mysql官网下载GPL免费版…

C++概念、头文件与c区别、变量、const关键字以及enum枚举

C概念 C最主要的就是&#xff1a;C是面向对象的编程思想&#xff0c;而C是面向过程的编程思想。C编写出来的效率比其他语言高的多。 C思想&#xff1a;万物皆对象 C语言的主要特点表现在两个方面&#xff0c;一是尽量兼容C,二是支持面向对象的方法。首先&#xff0c;C的确是一…

SNETCracker--超级弱口令检查工具简介

一、简介 SNETCracker 超级弱口令检查工具是一款Windows平台的弱口令审计工具&#xff0c;支持批量多线程检查&#xff0c;可快速发现弱密码、弱口令账号&#xff0c;密码支持和用户名结合进行检查&#xff0c;大大提高成功率&#xff0c;支持自定义服务端口和字典。 二、SNE…

Java集成结巴中文分词器、Springboot项目整合jieba分词,实现语句最精确的切分、自定义拆词

文章目录 一、jieba介绍二、集成三、原理四、自定义拆词4.1、方式一&#xff1a;在源码的dict.txt中修改然后重新打包(推荐)4.2、新建文件自定义拆词 五、其他问题 一、jieba介绍 jieba是一个分词器&#xff0c;可以实现智能拆词&#xff0c;最早是提供了python包&#xff0c;…

迪拜之行回顾:CESS 的 DePIN 创新之旅

迪拜最近是一个关键热词&#xff0c;成为了一系列 Web3 和加密活动的中心&#xff0c;吸引了行业领导者、创新者和爱好者&#xff0c;探索区块链和去中心化技术的最新发展。从 4 月中旬&#xff0c;一系列行业会议和活动陆续举行&#xff0c;吸引了一众与会者。然而暴雨积水又成…

2023平航杯——手机取证复现

手机最近连接的wifi"只有红茶可以吗"的密码是&#xff1f;【标准格式&#xff1a;ABCabc123!#】 手机上安装了某个运动软件&#xff0c;它的包名是&#xff1f;【标准格式&#xff1a;com.baidu.gpt】 com.dizhisoft.changdongli 该运动软件中最近一次运动记录的起点…

NodeJS操作符空格漏洞

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境&#xff0c;它使得 JavaScript 可以脱离浏览器在服务器端运行。Node.js 利用事件驱动、非阻塞 I/O 模型等技术提高了性能&#xff0c;从而在开发领域得到广泛应用&#xff0c;比如Web服务应用&#xff08;尤其是非阻塞…

Python+Appium实现自动化测试

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、环境准备 1.脚本语言&#xff1a;Python3.x IDE&#x…

Yolov5 export.py实现onnx模型的导出

查了很多资料&#xff0c;很多用python代码写的&#xff0c;只需要这个库那个库的&#xff0c;最后都没成功。 不如直接使用Yolov5里面的 export.py实现模型的转换。 一&#xff1a;安装依赖 因为yolov5里面的requirments.txt是将这些转换模型的都注释掉了 所以需要解除注释…

SAP如何批量标记生产订单的TECO状态

声明&#xff1a;本文仅代表作者观点和立场&#xff0c;不代表任何公司&#xff01;仅用于SAP软件应用学习参考。 SAP/ERP系统生产订单完工后&#xff0c;在进行结算之前&#xff0c;需要进行技术性完成操作&#xff0c;即将生产订单批量标记TECO&#xff0c;标记上TECO表示生…

独立站运营教程:站外引流如何做?

在当今全球化的商业环境中&#xff0c;跨境电商已经成为一个蓬勃发展的行业。对于跨境电商独立站来说&#xff0c;站外引流是非常关键的一环&#xff0c;它可以帮助独立站吸引更多潜在客户&#xff0c;提升品牌知名度&#xff0c;促进销售增长。本文将深入探讨如何实现跨境电商…