队列及其实现

news2025/4/16 10:23:08

目录

一:队列

1.队列的概念及结构

2.队列的实现

<1>.初始化队列

<2>.队尾入队列

<3>.队头出队列

<4>.获取队列头部元素

<5>.获取队列队尾元素

<6>.获取队列中有效元素个数 

<7>.销毁队列 

二:完整代码


一:队列

1.队列的概念及结构


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

2.队列的实现


队列的实现可以通过数组实现,也可以通过链表实现,在此处,如果使用数组实现的话,出的队列在数组头上出数据,效率很低,在此处,我们选择泳联表来实现。


 需要创建链式结构和队列的结构:

 typedef int QDataType;

 //链式结构:表示队列 
typedef struct QListNode
{
    struct QListNode* _next;
    QDataType _data;
}QNode;

// 队列的结构 
typedef struct Queue
{
    QNode* _front;//队头
    QNode* _rear;//队尾
    int size;
}Queue;                                                                                                                       

<1>.初始化队列


void QueueInit(Queue* q);


令队头,队尾为空,队列中的元素个数为 0 .

代码为:

// 初始化队列 
void QueueInit(Queue* q)
{
	assert(q);

	q-> _rear = NULL;
	q-> _front = NULL;
	q->size = 0;
}

<2>.队尾入队列


 void QueuePush(Queue* q, QDataType data);


 在队列尾部,入队列,本质上是对链表进行操作,需要开辟一个一个新的节点,将其于队列中的内容链接起来,最后对元素总数进行 ++ 操作。

 画图分析如下:

 代码为:

// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{
	assert(q);

	//插入数据 --- 链表 --- 开辟新的节点(结构体)
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->_data = data;
	newnode->_next = NULL;

	//判断队列中是否有元素
	if (q->_rear == NULL)
	{
		assert(q->_front == NULL);
		//相当于对链表进行头插
		q->_front = q->_rear = newnode;
	}
	else
	{
		//相当于在队列的结尾,插入一个结构体
		q->_rear->_next = newnode;
		q->_rear = newnode;
	}
	q->size++;
}

<3>.队头出队列


 void QueuePop(Queue* q);


在出队列时,我们需要考虑队列中是否有元素,若队列为空,则无法进行出队列操作 --- 即需要对链表进行判空。若队列中有元素,则需要考虑队列中有几个节点:若队列中只有一个节点,进行出队列操作一次后,队列即为空。若队列中有多个节点时,可以开辟一个新的节点用于记录头节点的下一个位置,然后释放头节点,将开辟的新节点看作队列的队头。

画图分析:

 

 代码为:

// 检测队列是否为空,如果为空返回零结果
int QueueEmpty(Queue* q)
{
	assert(q);

	return q->_rear == NULL;
}
// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);

	//需要判断队列中是否有元素 --- 若队列为空,则无法进行出队列
	assert(!QueneEmpty(q));

	//判断有几个节点 --- 一个节点 --- 多个节点
	if (q->_front->_next == NULL)
	{
		free(q->_front);
		q->_front = NULL;
		q->_rear = NULL;
	}
	else
	{
		QNode* next = q->_front->_next;
		free(q->_front);
		q->_front = next;
	}
	q->size--;
}

<4>.获取队列头部元素


 QDataType QueueFront(Queue* q);


获取队列头部元素时,需要判断队列是否为空,若队列为空,则无队列头部元素。

获取头部元素 q->_front_data

代码为:

// 检测队列是否为空,如果为空返回零结果
int QueueEmpty(Queue* q)
{
	assert(q);

	return q->_rear == NULL;
}


// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{
	assert(q);
	//需要判断队列中是否有元素 --- 若队列为空,则无队列头部元素
	assert(!QueneEmpty(q));

	return q->_front->_data;
}

<5>.获取队列队尾元素


 QDataType QueueBack(Queue* q);


获取队列队尾元素时,需要判断队列中是否有元素,即需要判断队列是否为空。

获取尾部元素 q->_rear->_data

代码为:

// 检测队列是否为空,如果为空返回零结果
int QueueEmpty(Queue* q)
{
	assert(q);

	return q->_rear == NULL;
}


// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{
	assert(q);
	//需要判断队列中是否有元素 --- 若队列为空,则无队列尾q元素
	assert(!QueneEmpty(q));

	return q->_rear->_data;
}

<6>.获取队列中有效元素个数 


int QueueSize(Queue* q);


我们在入队列时,进行了q->_size++ , 出队列时,进行 q->_size-- 。

即 q->_size 即为队列中有效元素的个数。

代码为:

// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{
	assert(q);

	return q->size;
}

<7>.销毁队列 


void QueueDestroy(Queue* q);


队列内部建立的是链表结构,而链表在释放的时候需要一个一个销毁,在此时,我们需要建立一个结构体指针指向队列的头部(QNode* cur = q->_front),然后一个一个地释放节点,循环条件更替条件为:cur = cur->_next , 当 cur 为空时,循环结束。然后将队列的内部元素置为空或者0。

画图分析:

 代码为:

// 销毁队列 
void QueueDestroy(Queue* q)
{
	assert(q);
	//链表需要一个一个销毁 -- 修改的为链表
	QNode* cur = q->_front;

	while (cur)
	{
		QNode* next = cur->_next;
		free(cur);
		cur = next;
	}

	q->size = 0;
	q->_front = NULL;
	q->_rear = NULL;
}

二:完整代码

 queue.h

#pragma once

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

typedef int QDataType;

 //链式结构:表示队列 
typedef struct QListNode
{
	struct QListNode* _next;
	QDataType _data;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* _front;//队头
	QNode* _rear;//队尾
	int size;
}Queue;

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

queue.c

#include"quene.h"

// 初始化队列 
void QueueInit(Queue* q)
{
	assert(q);

	q-> _rear = NULL;
	q-> _front = NULL;
	q->size = 0;
}

// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{
	assert(q);

	//插入数据 --- 链表 --- 开辟新的节点(结构体)
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->_data = data;
	newnode->_next = NULL;

	//判断队列中是否有元素
	if (q->_rear == NULL)
	{
		assert(q->_front == NULL);
		//相当于对链表进行头插
		q->_front = q->_rear = newnode;
	}
	else
	{
		//相当于在队列的结尾,插入一个结构体
		q->_rear->_next = newnode;
		q->_rear = newnode;
	}
	q->size++;
}

// 检测队列是否为空,如果为空返回零结果
int QueueEmpty(Queue* q)
{
	assert(q);

	return q->_rear == NULL;
}
// 队头出队列 
void QueuePop(Queue* q)
{
	assert(q);

	//需要判断队列中是否有元素 --- 若队列为空,则无法进行出队列
	assert(!QueneEmpty(q));

	//判断有几个节点 --- 一个节点 --- 多个节点
	if (q->_front->_next == NULL)
	{
		free(q->_front);
		q->_front = NULL;
		q->_rear = NULL;
	}
	else
	{
		QNode* next = q->_front->_next;
		free(q->_front);
		q->_front = next;
	}
	q->size--;
}

// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{
	assert(q);
	//需要判断队列中是否有元素 --- 若队列为空,则无队列头部元素
	assert(!QueneEmpty(q));

	return q->_front->_data;
}


// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{
	assert(q);
	//需要判断队列中是否有元素 --- 若队列为空,则无队列尾q元素
	assert(!QueneEmpty(q));

	return q->_rear->_data;
}

// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{
	assert(q);

	return q->size;
}

// 销毁队列 
void QueueDestroy(Queue* q)
{
	assert(q);
	//链表需要一个一个销毁 -- 修改的为链表
	QNode* cur = q->_front;

	while (cur)
	{
		QNode* next = cur->_next;
		free(cur);
		cur = next;
	}

	q->size = 0;
	q->_front = NULL;
	q->_rear = NULL;
}

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

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

相关文章

如何完全卸载IDEA

工欲善其事必先利其器&#xff0c;我们在用idea的时候&#xff0c;idea的环境出现了莫名其妙的问题&#xff0c;怎么也找不到问题原因。有时候也可能是安装了不知名VB脚本&#xff0c;给系统装了一大堆的环境变量(如下图所示)&#xff0c;这个时候你可以试着把idea卸载重新安装…

Jetpack Compose UI预览

Android开发 Jetpack_Compose_2 UI预览Preview 前言 在学习jetpack compose如何编写ui之前&#xff0c;我认为还是应该先了解与Android studio配合的UI预览Preview。 这样就可以立刻看到UI效果&#xff0c;从而方便后续学习验证代码。 所需依赖 implementation "androidx…

CAPL(vTESTStudio) - 自动创建带有时间戳的报告和log

目录 getLocalTime - 获取本地时间函数 代码示例 获取当前时间并形成格式:"2023_05_22_23_20_18"

Qt中的坐标系

Qt中的坐标系 Qt中的坐标系与win10上画图工具的联系 上面这个图片的水印挡住了重要信息,然后又截了一张,显然,画图工具的像素就是Qt中的坐标系,所以,以后查坐标系直接打开Qt:画笔位置所显示的像素就是Qt的坐标!!! 再总结一下: 好奇:win10上的画图工具是qt写的吗? 答: 不是…

【SpringCloud】Nacos

文章目录 一、Nacos1、安装2、服务注册和发现3、服务分级存储模型4、负载均衡策略--NacosRule5、服务实例的权重设置 一、Nacos 1、安装 官网&#xff1a;https://nacos.io/zh-cn/ 下载 Github主页: https://github.com/alibaba/nacos Github的Release下载页: https://githu…

linux命令行如何查看命令帮助信息

一&#xff0c;简介 “授之以鱼不如授之以渔”&#xff0c;我们再学习linux命令的时候&#xff0c;想查看某个命令的详细说明&#xff0c;有哪些方法呢&#xff1f;本文来介绍一下如何在命令行查找命令的帮助信息。 二&#xff0c;linux命令格式介绍 Linux命令一般由三部分组…

【深度学习】- 作业1: Softmax实现手写数字识别

课程链接: 清华大学驭风计划 代码仓库&#xff1a;Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的&#xff0c;其分为四门课&#xff0c;包括: 机器学习(张敏教授) &#xff0c; 深度学习(胡晓林教授), 计算…

【深度学习】 - 作业7: 图像超分辨率重建

课程链接: 清华大学驭风计划 代码仓库&#xff1a;Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭风计划是由清华大学老师教授的&#xff0c;其分为四门课&#xff0c;包括: 机器学习(张敏教授) &#xff0c; 深度学习(胡晓林教授), 计算…

Linux网络编程—Day10

Linux服务器程序规范 Linux服务器程序一般以后台进程形式运行。后台进程又称守护进程。它没有控制终端&#xff0c;因而也不会意外接收到用户输入。 守护进程的父进程通常是init进程&#xff08;PID为1的进程&#xff09;&#xff1b;Linux服务器程序通常有一套日志系统&#…

Android 11.0 系统设置显示主菜单添加屏幕旋转菜单实现旋转屏幕功能

1.前言 在android11.0的系统rom定制化开发中,在对系统设置进行定制开发中,有产品需求要求增加 旋转屏幕功能的菜单,就是在点击旋转屏幕菜单后弹窗显示旋转0度,旋转 90度,旋转180度, 旋转270度针对不同分辨率的无重力感应的大屏设备的屏幕旋转功能的实现, 接下来就来分析…

chatgpt赋能Python-python_dill

Python dill - 更高效&#xff0c;更强大的对象序列化工具 在Python编程中&#xff0c;对象序列化是一个非常常见的操作&#xff0c;它将Python对象转换为可以存储或传输的格式。Python默认提供了pickle模块来实现序列化&#xff0c;但是pickle存在一些限制&#xff0c;比如无…

usb摄像头驱动-core层usb设备的注册

usb摄像头驱动-core层driver.c 文章目录 usb摄像头驱动-core层driver.cusb_bus_typeusb_device_matchusb_uevent usb_register_driver 在ubuntu中接入罗技c920摄像头打印的信息如下&#xff1a; 在内核中&#xff0c;/driver/usb/core/driver.c 文件扮演了 USB 核心驱动程序管…

复现ms17-010漏洞

复现ms17-010 复现条件环境操作效果 让我们来看看“hkl”在干嘛 复现 条件 1.靶机必须为win8以下。 2.靶机必须同攻击机处于相同网段&#xff08;即倒数第二位相同&#xff09;。 3.靶机的445端口必须要开启。 环境 虚拟机kali为攻击机&#xff0c;win7虚拟机为靶机。 kali…

SELECT LAST_INSERT_ID()自增主键冲突或者为0问题

问题 数据库为mysql&#xff1b; mapper.xml文件为mybatis-generator自动生成的&#xff1b; 连接池使用DruidDataSource&#xff1b; 最终生成的insertSelective如下&#xff1a; 出现问题&#xff1a; 主键冲突&#xff1a;[WMyBatisTraceInterceptor:54][com.mysql.jdbc.…

如何定位OOM

造成OOM的原因 定位OOM 针对第一和第二种情况需要定位OOM 系统已经挂了&#xff1a; 通过堆dump文件定位。 当JVM发生OOM时&#xff0c;自动生成DUMP文件&#xff1a; -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPath${目录} java -Xms10M -Xmx10M -XX:HeapDumpOnOutOfMemo…

c#中的json数据

JSON数据 数据传输的语言&#xff0c;用于前后端数据交互的语言&#xff0c;注意xml的区别。 json和xml的区别 xml&#xff1a;可扩展标记语言&#xff0c;是一种用于标记电子文件使其具有结构性的标记语言。 json&#xff1a;(JavaScript Object Notation, JS 对象简谱) 是…

昆仲被投企业「鲲游光电」近期完成新一轮数亿元融资,继续致力于探索前沿光电子领域产品与创新应用|昆仲·链

鲲游光电(North Ocean Photonics)是专注于晶圆级光学、光集成领域的高科技企业&#xff0c;总部位于中国上海。依托自身深厚的技术积累、高精度的制造工艺&#xff0c;鲲游光电通过融合集成光学与集成电路的创新思路&#xff0c;致力于探索前沿光子、光电子领域的实现与创新应用…

MyBatis环境搭建配置、增删改查操作、分页、事务操作、动态SQL、缓存机制、注解开发

MyBatis 文章目录 MyBatisXML语言简介用途各部分注解声明元素属性注释CDATA转义字符 搭建环境读取实体类创建实体与映射关系的文件 配置MyBatis创建工具类接口实现 Mybatis工作流程增删改查指定映射规则指定构造方法字段名称带下划线处理条件查询插入数据复杂查询和事务一对多查…

Codeforces Round 860 (Div. 2)

A Showstopper 题意&#xff1a;给你两个长度为n的数组a和b&#xff0c;每次操作你可以互换a[i]与b[i]&#xff0c;问最终能否满足 思路&#xff1a;若a[i]>b[i]&#xff0c;我们就进行操作。这样数组b元素都是较大的&#xff0c; 一定比不操作更优。最后判断是否满足条件…

Python中的异常处理机制

什么是异常与异常处理 异常就是错误 异常会导致程序崩溃并停止运行 能监控并捕获到异常&#xff0c;将异常部位的程序进行修理使得程序继续正常运行 异常的语法结构 try:<代码块1> 被try关键字检查并保护的业务代码except <异常的类型>:<代码块2> # 代码…