【数据结构】队列(Queue)的实现 -- 详解

一、队列的概念及结构

1、概念

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出 FIFO(First In First Out)。


入队列:进行插入操作的一端称为队尾

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


2、结构


(1)队列的顺序存储结构

 

  • 入队,不需要移动任何元素,时间复杂度为 O(1)
  • 出队,所有元素需要往前移动,时间复杂度为 O(N)

(2)队列的链表存储结构

首先我们定义两个指针,队头指针指向第一个节点,队尾指针指向尾节点。

  • 入队(尾插),时间复杂度为 O(1)
  • 出队(头删),时间复杂度为 O(1)

 二、队列的实现


1、创建文件

  • test.c(主函数、测试队列各个接口功能)
  • Queue.c(队列接口函数的实现)
  • Queue.h(队列的类型定义、接口函数声明、引用的头文件)

2、Queue.h 头文件代码

// Queue.h
// 链式结构:表示队列
#pragma once
#include<stdio.h>
#include<stdbool.h> //bool
#include<assert.h> // assert
#include<stdlib.h> // malloc

typedef int QDataType;

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

typedef struct Queue // 队列的链式结构
{ 
    QueueNode* head;  //队头指针
	QueueNode* tail;  //队尾指针
}Queue; 

// 初始化队列
void QueueInit(Queue* pq); 
// 销毁队列
void QueueDestroy(Queue* pq);
// 队尾入队列
void QueuePush(Queue* pq, QDataType data); 
// 队头出队列
void QueuePop(Queue* pq); 
// 获取队列头部元素
QDataType QueueFront(Queue* pq); 
// 获取队列队尾元素
QDataType QueueBack(Queue* pq); 
// 获取队列中有效元素个数
int QueueSize(Queue* pq); 
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* pq); 

三、Queue.c 中各个接口函数的实现

1、初始化队列

// 初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
}

2、队列的销毁

// 销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->head;
	while (cur)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
    cur = NULL;
	pq->head = pq->tail = NULL;
}

3、队尾入队列(尾插)

// 队尾入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode)); // 动态申请一个节点
	newnode->data = x;
	newnode->next = NULL; // 尾节点next指针置空

	if (pq->head == NULL) // 队列为空
	{
		pq->head = pq->tail = newnode;
	}
	else // 队列不为空
	{
		pq->tail->next = newnode;
		pq->tail = newnode; // 更新队尾指针
	}
}

4、队头出队列(头删)

// 队头出队列
void QueuePop(Queue* pq)
{
	assert(pq);

	//温柔处理方式:
	/* if(pq->head == NULL)
	    return; */

	//暴力处理方式:
	assert(!QueueEmpty(pq));

	QueueNode* next = pq->head->next; // 记录头节点的直接后继
	free(pq->head); // 释放头节点
	pq->head = next; // 更新队头指针
	if (pq->head == NULL) // 队列中只有一个节点
	{
		pq->tail = NULL;
	}
}

5、获取队列头部元素

// 获取队列头部元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->head->data;
}

6、获取队列队尾元素

// 获取队列队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));
	return pq->tail->data;
}

7、获取队列中有效元素个数

// 获取队列中有效元素个数
int QueueSize(Queue* pq)
{
	assert(pq);
	int n = 0;
	QueueNode* cur = pq->head;
	while (cur)
	{
		n++;
		cur = cur->next;
	}
	return n;
}

如果频繁调用这个接口函数,可以在 QueuePtr 中加一个 size 来记录数据的个数。 


8、检查队列是否为空

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* pq);
{
	assert(pq);
	return pq->head == NULL && pq->tail == NULL;
}

四、整合代码

// Queue.c
#include "Queue.h"

// 初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
}

// 销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QueueNode* cur = pq->head;
	while (cur)
	{
		QueueNode* next = cur->next;
		free(cur);
		cur = next;
	}
    cur = NULL;
	pq->head = pq->tail = NULL;
}

// 队尾入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode)); // 动态申请一个节点
	newnode->data = x;
	newnode->next = NULL; // 尾节点next指针置空

	if (pq->head == NULL) // 队列为空
	{
		pq->head = pq->tail = newnode;
	}
	else // 队列不为空
	{
		pq->tail->next = newnode;
		pq->tail = newnode; // 更新队尾指针
	}
}

// 队头出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	QueueNode* next = pq->head->next; // 记录头节点的直接后继
	free(pq->head); // 释放头节点
	pq->head = next; // 更新队头指针
	if (pq->head == NULL) // 队列中只有一个节点
	{
		pq->tail = NULL;
	}
}

// 获取队列头部元素
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;
}

// 获取队列中有效元素个数
int QueueSize(Queue* pq)
{
	assert(pq);
	int n = 0;
	QueueNode* cur = pq->head;
	while (cur)
	{
		n++;
		cur = cur->next;
	}
	return n;
}

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* pq);
{
	assert(pq);
	return pq->head == NULL && pq->tail == NULL;
}

五、测试队列的功能



六、拓展 

实际中我们有时还会使用一种队列叫循环队列。环形队列可以使用数组实现,也可以使用循环链表实现。


1、空的循环队列


2、满的循环队列

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

当ChatGPT应用在汽车行业,具体有哪些场景?

​ ChatGPT有潜力彻底改变汽车行业并将其提升到新的高度。在ChatGPT的加持下&#xff0c;该行业的多个领域都将取得重大变化。 利用ChatGPT作更高级的虚拟助理 你可能用过现有的虚拟助理&#xff0c;它们一系列的回复有时候让人不得不感叹一句“人工智障”&#xff01;然而&a…

Android Glide预处理preload原始图片到成品resource 预加载RecyclerViewPreloader,Kotlin

Android Glide预处理preload原始图片到成品resource & 预加载RecyclerViewPreloader&#xff0c;Kotlin <uses-permission android:name"android.permission.READ_EXTERNAL_STORAGE" /><uses-permission android:name"android.permission.READ_MED…

RT1052的定时器

文章目录 1 通用定时器1.1 定时器框图1.2 实现周期性中断 2 相关寄存器3 定时器配置3.1 时钟使能3.2 初始化GPT1定时器3.2.1 base3.2.2 initConfig3.2.2.1 clockSorce3.2.2.2 divider3.2.2.3 enablexxxxx 3.3 设置 GPT1 比较值3.3.1 base3.3.2 channel3.3.3 value 3.4 设置 GPT…

合并两个有序数组——力扣88

文章目录 题目描述法一 双指针法二 逆向双指针 题目描述 法一 双指针 使用双指针方法&#xff0c;将两个数组看作队列&#xff0c;每次从两个数组头部取出比较小的数字放到结果中。 void merge(vector<int>&nums1, int m,vector<int>&nums2, int n){int p1…

什么是DOTS?

(图片为实机测试) DOTS全称&#xff1a;&#xff08;Burst Job SystemEntity Component System&#xff09; 新型高性能、多线程面向数据的技术堆栈 是由&#xff1a;BrustJob System ECS组合而成&#xff0c;是一种面向数据对象的编程体系&#xff0c;在unity中您也可以对…

Psim 2022电力仿真--锁相环控制程序

目录 目录 1.原理 2.代码实现 3.仿真实现 4.仿真结果 5.讨论 1.原理 三相锁相环是一种用于控制交流&#xff08;AC&#xff09;信号的相位、频率和波形的电路&#xff0c;其原理和应用也广泛用于电源领域。使用三相锁相环可以使交流电源输出的电压稳定、精准地与输入信号…

如何降低TCP在局域网环境下的数据传输延迟

以Ping为例。本案例是一个测试题目&#xff0c;只有现象展示&#xff0c;不含解决方案。 ROS_Kinetic_26 使用rosserial_windows实现windows与ROS master发送与接收消息_windows 接收ros1 消息 什么是ping&#xff1f; AI&#xff1a; ping是互联网控制消息协议&#xff08;…

国内 github.com经常打不开的解决办法

1、打开网站http://tool.chinaz.com/dns/ 2、在A类型中填写github.com,再点击监测按钮 3、复制下面任意一个ip 4、打开电脑文件C:\Windows\System32\drivers\etc下的host文件 5、在host文件的最后一刚加入刚才复制的IP 6、重新打开GitHub

tensorRT模型性能测试

目录 前言1. 模型训练1.1 模型1.2 数据集1.3 xml2yolo1.4 yolo2json1.5 json2yolo1.6 训练 2. TRT模型转换2.1 YOLOv5 ONNX导出2.2 YOLOv6 ONNX导出2.3 YOLOv5 engine生成2.4 YOLOv6 engine生成 3. TRT模型测试3.1 YOLOv5 engine mAP测试3.2 YOLOv5 engine 速度测试3.3 YOLOv6 …

第120天:免杀对抗-防朔源防流量防特征CDN节点SSL证书OSS存储上线

知识点 #知识点&#xff1a; 1、CS-CDN节点-防拉黑 2、CS-SSL证书-防特征 3、CS-OSS存储-防流量#章节点&#xff1a; 编译代码面-ShellCode-混淆 编译代码面-编辑执行器-编写 编译代码面-分离加载器-编写 程序文件面-特征码定位-修改 程序文件面-加壳花指令-资源 代码加载面-D…

【ARM】内核驱动之设备树的学习-长文

❤️作者主页:凉开水白菜 ❤️作者简介:共同学习,互相监督,热于分享,多加讨论,一起进步! ❤️点赞 👍 收藏 ⭐再看,养成习惯 订阅的粉丝可通过PC端文末加我微信,可对文章的内容进行一对一答疑! 文章目录 一、什么是设备树,为什么叫设备树?二、如何编译设备树?三、…

【语音控制SU-03T的使用】

语音控制SU-03T的使用 最近入手了SU-03T型号的语音模块&#xff0c;下面记录一下使用方式。相对于LD3320语音模块来说SU-03T更智能、使用更方便&#xff0c;从价格来讲也相对便宜&#xff0c;需要的可以在淘宝自行购买。 引脚详解一、智能公元/AIOT产品化平台配置 智能公元链接…

React井字棋游戏官方示例

在本篇技术博客中&#xff0c;我们将介绍一个React官方示例&#xff1a;井字棋游戏。我们将逐步讲解代码实现&#xff0c;包括游戏的组件结构、状态管理、胜者判定以及历史记录功能。让我们一起开始吧&#xff01; 项目概览 在这个井字棋游戏中&#xff0c;我们有以下组件&am…

【数据预测】基于蜣螂优化算法DBO的VMD-KELM光伏发电功率预测 短期功率预测【Matlab代码#53】

文章目录 【可更换其他算法&#xff0c;获取资源请见文章第6节&#xff1a;资源获取】1. 蜣螂优化算法DBO2. 变分模态分解VMD3. 核极限学习机KELM4. 部分代码展示5. 仿真结果展示6. 资源获取 【可更换其他算法&#xff0c;获取资源请见文章第6节&#xff1a;资源获取】 1. 蜣螂…

Vulnhub: hacksudo: search靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.170 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.170 80端口目录爆破 feroxbuster -k -d 1 --url http://192.168.111.170 -w /opt/zidian/SecLists-2022.2/Discovery/Web…

机器学习之Boosting和AdaBoost

1 Boosting和AdaBoost介绍 1.1 集成学习 集成学习 (Ensemble Learning) 算法的基本思想就是将多个分类器组合&#xff0c;从而实现一个预测效果更好的集成分类器。 集成学习通过建立几个模型来解决单一预测问题。它的工作原理是生成多个分类器/模型&#xff0c;各自独立地学…

ChatGPT长文本对话输入方法

ChatGPT PROMPTs Splitter 是一个开源工具&#xff0c;旨在帮助你将大量上下文数据分成更小的块发送到 ChatGPT 的提示&#xff0c;并根据如何处理所有块接收到 ChatGPT&#xff08;或其他具有字符限制的语言模型&#xff09;的方法。 推荐&#xff1a;用 NSDT设计器 快速搭建可…

iOS开发-NotificationServiceExtension实现实时音视频呼叫通知响铃与震动

iOS开发-NotificationServiceExtension实现实时音视频呼叫通知响铃与震动 在之前的开发中&#xff0c;遇到了实时音视频呼叫通知&#xff0c;当App未打开或者App在后台时候&#xff0c;需要通知到用户&#xff0c;用户点击通知栏后是否接入实时音视频的视频或者音频通话。 在…

【雕爷学编程】MicroPython动手做(17)——掌控板之触摸引脚

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

ChatGLM-6B 部署与 P-Tuning 微调实战-使用Pycharm实战

国产大模型ChatGLM-6B微调部署入门-使用Pycharm实战 1.ChatGLM模型介绍 ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型&#xff0c;基于 General Language Model (GLM) 架构&#xff0c;具有 62 亿参数。结合模型量化技术&#xff0c;用户可以在消费级的显卡上进行本…