【数据结构】队列的实现(链式)

文章目录

  • 队列
    • 1.队列的概念及结构
      • 概念
      • 结构
    • 2.队列的实现(链式结构)
      • 队列定义
      • 初始化队列
      • 入队
      • 出队
      • 获取队头元素
      • 获取队尾元素
      • 销毁队列
      • 判断队列是否为空
      • 队列有效个数
    • 完整代码(包含测试代码)
      • Queue.h
      • Queue.c
      • test.c

队列

1.队列的概念及结构

概念

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

结构

队列也可以数组和链表的结构实现:

队列的顺序结构
入队,直接下标访问,时间复杂度为O(1)
出队,挪动数据覆盖,时间复杂度为O(N)

队列的链式结构
定义两个指针,队头指针指向第一个节点,队尾指针指向尾节点
入队(尾插),时间复杂度为O(1)
出队(头删),时间复杂度为O(1)

所以使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
在这里插入图片描述

2.队列的实现(链式结构)

首先新建一个工程:

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

完整的代码放在后面(包括测试代码),这里就不会展示测试的效果图。大家可以自己别敲边按测试代码测试。图解会写的很详细的,么么😙

队列定义

typedef int QDataType;

//队列结点结构
typedef struct QlistNode 
{
    QDataType val;//结点元素
    struct QlistNode* next;//结点指针
}QNode;

//队列链式结构
typedef struct Queue
{
    QNode* phead;//队头指针
    QNode* ptail;//队尾指针
    int size;//元素个数
}Queue;

初始化队列

初始化这里很讲究的,如果不把两个指针放到结构体里面封装起来,单独来传,那这里很麻烦要用二级指针而且也不太好控制,但是如果用结构体封装起来我们访问这两指针就是访问结构体的成员,要修改就直接修改指向结构体的指针pq就ok了
我们链表那里就讲过了传参的问题,我们实现无头链表的头插头删接口时,因为需要改变头指针的指向两种方法:
1、传二级指针
2、返回值(return)
现在又有了一种方法:
结构体封装起来

//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

入队

这个其实就是链表的尾插

//入队
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));//动态申请一个结点
	if (newnode == NULL)//判断结点是否申请成功
	{
		perror("malloc fail");
		return;
	}
	newnode->val = x;
	newnode->next = NULL;
	if (pq->phead==NULL)//队列为空插入
	{
		pq->phead = pq->ptail = newnode;
	}
	else//队列有元素
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}

出队

这个也就是链表的头删

//出队
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->phead);//队列不能为空

	if (pq->phead->next==NULL)//队列只有一个元素
	{
		pq->ptail = NULL;
	}
	QNode* del = pq->phead;
	pq->phead = pq->phead->next;
	free(del);
	del = NULL;
	pq->size--;

}

获取队头元素

//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);//队列不能为空

	return pq->phead->val;
}

获取队尾元素

//获取队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);//队列不能为空

	return pq->ptail->val;
}

销毁队列

//销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* pcur = pq->phead;
	while (pcur)
	{
		QNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pcur = NULL;
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}

判断队列是否为空

//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL;//pq->phead、pq->ptail两个用哪一个都行
}

队列有效个数

//队列有效个数
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
	
}

完整代码(包含测试代码)

Queue.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int QDataType;

//队列结点结构
typedef struct QlistNode 
{
    QDataType val;//结点元素
    struct QlistNode* next;//结点指针
}QNode;

//队列链式结构
typedef struct Queue
{
    QNode* phead;//队头指针
    QNode* ptail;//队尾指针
    int size;//元素个数
}Queue;


//初始化队列
void QueueInit(Queue* pq);
//入队
void QueuePush(Queue* pq, QDataType x);
//出队
void QueuePop(Queue* pq);
//获取队头元素
QDataType QueueFront(Queue* pq);
//获取队尾元素
QDataType QueueBack(Queue* pq);
//销毁队列
void QueueDestroy(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);
//队列有效个数
int QueueSize(Queue* pq);


Queue.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"queue.h"



//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
//入队
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));//动态申请一个结点
	if (newnode == NULL)//判断结点是否申请成功
	{
		perror("malloc fail");
		return;
	}
	newnode->val = x;
	newnode->next = NULL;
	if (pq->phead==NULL)//队列为空插入
	{
		pq->phead = pq->ptail = newnode;
	}
	else//队列有元素
	{
		pq->ptail->next = newnode;
		pq->ptail = newnode;
	}
	pq->size++;
}
//出队
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->phead);//队列为空中止
	if (pq->phead->next==NULL)//队列只有一个元素
	{
		pq->ptail = NULL;
	}
	QNode* del = pq->phead;
	pq->phead = pq->phead->next;
	free(del);
	del = NULL;
	pq->size--;

}
//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->phead);
	return pq->phead->val;
}
//获取队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->ptail);
	return pq->ptail->val;
}
//销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);
	QNode* pcur = pq->phead;
	while (pcur)
	{
		QNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	pcur = NULL;
	pq->phead = NULL;
	pq->ptail = NULL;
	pq->size = 0;
}
//判断队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->phead == NULL;
}
//队列有效个数
int QueueSize(Queue* pq)
{
	assert(pq);
	return pq->size;
	
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Queue.h"


int main()
{
	Queue Q;
	QueueInit(&Q);
	QueuePush(&Q, 1);
	QueuePush(&Q, 2);
	QueuePush(&Q, 3);
	QueuePush(&Q, 4);
	QueuePush(&Q, 5);
	//打印队列
	//while (!QueueEmpty(&Q))
	//{
	//	printf("%d ", QueueFront(&Q));
	//	QueuePop(&Q);
	//}
	//printf("\n");

	int r = QueueSize(&Q);
	printf("%d ", r);

	//printf("%d ", QueueBack(&Q));


	return 0;
}

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

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

相关文章

PCIE/PCI设备配置空间

PCI/PCIE Capability PCI/PCIE设备的配置空间记录了PCIE设备的capability支持信息&#xff0c;每个capability定义了一个ID标识&#xff0c;可以通过函数pci_find_capability和pci_find_ext_capability来探测和获取这些配置信息的位置。这些ID定义在文件include/uapi/linux/pc…

vue2+Ts中openLayer绘图工具组件封装

vue2Ts中openLayer绘图工具组件封装 效果&#xff1a; 封装组件代码&#xff1a; <!-- openLayer绘图工具 --> <template><a-button-group v-show"isShow"><a-button v-if"shouldShowButton(point)" click"draw(Point)"…

linux的 /usr/sbin/nologin /sbin/nologin /bin/false /etc/nologin 的作用与区别

/usr/sbin/nologin /sbin/nologin /bin/false /etc/nologin 的作用与区别 /usr/sbin/nologin /sbin/nologin /bin/false 这三者的作用几乎一样&#xff0c;都是禁止用户登录。 /usr/sbin/nologin /sbin/nologin 是同一个文件&#xff0c;通过软连接指向。 当把用户的bash设置…

Malbers Inventory System

Inventory插件为Malbers动物管理员生态系统带来了强大的库存系统&#xff0c;具有以下功能&#xff1a;通知系统、库存集、自定义物品反应等 ✔️特征 项目管理 收集和存储项目 库存显示 通知系统 物品所有者 库存集合 项目操作 保存和加载&#xff08;基于JSON.Net&#xff0c…

在 CSS 中使用 text-emphasis 来增强文本的趣味性

在CSS中设置文本样式的方法有很多。您可以更改颜色、大小、字体&#xff0c;甚至添加阴影和轮廓等效果。但最近&#xff0c;我了解到一个我以前没有听说过的时尚 CSS 属性&#xff0c;它非常棒&#xff01; 它被称为文本强调&#xff08;text-emphasis&#xff09;&#xff0c…

python数据可视化:层次聚类热图clustermap()

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 python数据可视化&#xff1a; 层次聚类热图 clustermap() [太阳]选择题 请问关于以下代码表述错误的选项是&#xff1f; import seaborn as sns import matplotlib.pyplot as plt import n…

低成本窗帘电机解决方案KP81101 3.6A有刷直流电机H桥驱动器代替DRV8871

KP81101是一款有刷直流电机驱动器&#xff0c;适用于家用电器、工业设备和其他有刷直流电机、步进电机应用场合。驱动器由四个 NMOS 构成的 H 桥组成&#xff0c;两个逻辑输入控制全桥驱动器&#xff0c;以驱动直流有刷电机电流双向流动。驱动器的最大峰值电流能力为 3.6A。芯片…

Warning logs 2024-05-15

mysql数据库中文模糊查询时出现异常 Error querying database. Cause: java.sql.SQLException: Illegal mix of collations for operation like Select("select f.* from fundDetails f" " where (case when #{keyword} is not null then f.operateTime like c…

软件项目验收第三方测试报告如何获取

软件项目验收第三方测试报告是确保软件质量、安全性和稳定性的重要环节。对于企业和开发者来说&#xff0c;获取一份全面、专业的第三方测试报告&#xff0c;对于提升软件产品的竞争力和用户满意度至关重要。本文将介绍如何获取软件项目验收第三方测试报告&#xff0c;以及相关…

13.监控redis

1.状态信息 redis-cli keys * info select 0-15#16个库&#xff0c;依次查看即可2.导入模板 在zabbix-server界面-模板-导入-选择文件-redis.xml <?xml version"1.0" encoding"UTF-8"?> <zabbix_export><version>2.0</version&g…

全栈中VUE的install报错说taobao仓库不好使的解决办法

长话短说&#xff0c;就是报错了&#xff0c;直接上干货。 step1&#xff1a;查看设置&#xff0c;主要是看registry npm config getstep2&#xff1a;设置仓库 npm config set registry https://registry.npmmirror.comstep3&#xff1a;再运行步骤一的指令查看仓库是不是变…

Java 循环结构 - for, while 及 do...while

Java 循环结构 - for, while 及 do…while 顺序结构的程序语句只能被执行一次。 如果您想要同样的操作执行多次&#xff0c;就需要使用循环结构。 Java中有三种主要的循环结构&#xff1a; while 循环 do…while 循环 for 循环 在 Java5 中引入了一种主要用于数组的增强型 f…

刷代码随想录有感(66):回溯算法——组合问题的优化(剪枝)

代码&#xff1a;将for循环中i的搜索范围进行缩小&#xff0c;免去多余的不可能符合条件的操作。 for(int i start; i < n-(k-tmp.size())1;i) 实质是剪枝&#xff0c;拿n4,k4作比较&#xff1a; 显然结果只可能是[1,2,3,4]&#xff0c;选取顺序只可能是1-2-3-4&#xff…

Kafka 核心属性速览

目录 1. 背景 2. Kafka的核心属性 2.1. Broker 2.2. Partitions 2.3. Replicas 3. 实践 4. 参考 1. 背景 Kafka是一个流行队列组件&#xff08;在AWS上叫MSK&#xff09;&#xff0c;其他的队列还有rocketMQ、rabbitMQ。就我个人而言&#xff0c;我只是一个使用…

图文详解JUC:Wait与Sleep的区别与细节

目录 一.Wait() 二.Sleep() 三.总结Wait()与Sleep()的区别 一.Wait() 在Java中&#xff0c;wait() 方法是 Object类中的一个方法&#xff0c;用于线程间的协作。当一个线程调用wait() 方法时&#xff0c;它会释放对象的锁并进入等待状态&#xff0c;直到其他线程调用相同对…

Ps 滤镜:素描

Ps菜单&#xff1a;滤镜/滤镜库/素描 Filter/Filter Gallery/Sketch “素描”滤镜组中的滤镜可以将纹理添加到图像上&#xff0c;还适用于创建美术或手绘外观。许多“素描”滤镜在重绘图像时使用前景色和背景色。 半调图案 Halftone Pattern “半调图案”滤镜通过创建一种特定图…

【微信小程序开发(从零到一)【婚礼邀请函】制作】——任务分析和效果实现的前期准备(1)

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

【069】基于SpringBoot+Vue实现的企业资产管理系统

系统介绍 基于SpringBootVue实现的企业资产管理系统管理员功能有个人中心&#xff0c;用户管理&#xff0c;资产分类管理&#xff0c;资产信息管理&#xff0c;资产借出管理&#xff0c;资产归还管理&#xff0c;资产维修管理。用户可以对资产进行借出和归还操作。因而具有一定…

详解lighthouse通过命令行方式运行并生成html测试报告的方法

lighthouse可以通过命令行的方式运行并生成html报告&#xff0c;我们可以通过lighthouse --help 命令查看命令行的详细用法&#xff0c;在这里我仅列出最常用的命令行使用方法&#xff01; 常用lighthouse命令行参数详解 * --chrome-flags&#xff1a;传递自定义标志给Chrome…

动态el-form表单以及动态禁用

当右侧下拉框选中为 长期有效,那么左侧输入框为禁用状态; <el-form-item label"证明有效期" class"is-required"><div v-for"(item,index) in form.arrayDat" :key"index" style"width: 100%;display: flex;justify-co…