4.C_数据结构_队列

news2024/9/23 6:14:18

概述

什么是队列:

队列是限定在两端进行插入操作和删除操作的线性表。具有先入先出(FIFO)的特点

相关名词:

  • 队尾:写入数据的一段
  • 队头:读取数据的一段
  • 空队:队列中没有数据,队头指针 = 队尾指针
  • 满队:队列中存满了数据,队尾指针 + 1 = 队头指针

循环队列

1、基本内容

循环队列是以数组形式构成的队列数据结构。

循环队列的结构体如下:

typedef int data_t; //队列数据类型
#define N 64        //队列容量
typedef struct{
    data_t data[N]; //数据
    int front;      //队头位置,代表将要出队的位置
    int rear;       //队尾位置,代表将要入队的位置
}sequeue_t;

入队与出队示意图: 

 在循环队列中,fornt代表将要出队的位置,rear代表将要入队的位置。

  • 空队:当fornt = rear时,代表将要出队的地方还没有入队数据,因此整个队列为空。
  • 入队:当想要入队时,只需要向rear的位置填入数据即可入队,入队之后应该rear++,让rear指向下一个入队的位置。
  • 出队:当想要出队时,只需要从fornt的位置获取数据即可出队,出队之后应该fornt++,让fornt指向下一个要出队的位置。
  • 满队:当rear+1 = front时,代表已经满队(这里省略了%限定范围)
  • fornt与rear指向空间问题:在循环队列中,满队时会有一个冗余空间不能使用。

循环队列代码的文件构成:

  • sequeue.h:数据结构的定义、运算函数接口
  • sequeue.c:运算函数接口的实现
  • test.c:使用数据结构实现的应用功能代码

循环队列相关函数: 

  • 创建:sequeue* queue_create(void);
  • 删除:int queue_del(sequeue** pQueue); 
  • 入队列:int enter_queue(sequeue* pQueue,data_t value);
  • 出队列:int out_queue(sequeue* pQueue,data_t* value);

2、功能实现 

2.1 创建

创建循环队列就是申请空间,并让入队位置与出队位置相等,这代表队列为空。

具体代码实现如下:

/*
 * queue_create:创建队列
 * @ret  NULL--err  other--空队列指针
 * */
sequeue* queue_create(void){
	sequeue* pQueue = NULL;
	//1.申请空间
	pQueue = (sequeue*)malloc(sizeof(sequeue));
	if(pQueue == NULL){
		printf("malloc err\n");
		return NULL;
	}
	//2.初始化,front = rear代表空队列
	memset(pQueue->data,0,N*sizeof(data_t));
	pQueue->front = 0;
	pQueue->rear = 0;
	return pQueue;
} 

2.2 删除

删除就是释放申请的空间即可。

具体代码实现如下:

/*
 * queue_del:销毁队列
 * param pQueue:要销毁的队列
 * @ret  -1--err  0--success
 * */
int queue_del(sequeue** pQueue){
	//1.判断参数有效性
	if(*pQueue == NULL){
		printf("pQueue is NULL\n");
		return -1;
	}
	free(*pQueue);
	*pQueue = NULL;
	return 0;
}

2.3 入队列

入队列的示意图如 "1、基本内容" 中所示,只需要在rear处填入数据并把rear进行偏移即可。

注意:入队列时,需要判断队列是否已满

具体代码实现如下:

/*
 * enter_queue:入队列
 * param pQueue:要入哪一个队列
 * param value:要入队的数据
 * @ret  -1--err  0--success
 * */
int enter_queue(sequeue* pQueue,data_t value){
	//1.判断参数有效性
	if(pQueue == NULL){
		printf("pQueue is NULL\n");
		return -1;
	}
	//2.判断队列是否已满
	if( ((pQueue->rear+1)%N) == pQueue->front ){
		printf("queue is full\n");
		return -1;
	}
	//3.入队列,就是在rear出写入数据
	pQueue->data[pQueue->rear] = value;
	pQueue->rear = (pQueue->rear+1)%N;
	return 0;
}

2.4 出队列

出队列的示意图如 "1、基本内容" 中所示,只需要在front处取出数据并把front进行偏移即可。

注意:出队列时,需要判断队列是否为空

具体代码实现如下:

/*
 * out_queue:出队列
 * param pQueue:要出哪一个队列的数据
 * param value:要出队的数据存放的位置
 * @ret  -1--err  0--success
 * */
int out_queue(sequeue* pQueue,data_t* value){
	//1.判断参数有效性
	if(pQueue == NULL){
		printf("pQueue is NULL\n");
		return -1;
	}
	//2.判断队列是否为空
	if(pQueue->front == pQueue->rear){
		printf("queue is empty\n");
		return -1;
	}
	//3.出队列,就是从front处读数据
	*value = pQueue->data[pQueue->front];
	pQueue->front = (pQueue->front+1)%N;
	return 0;
}

链式队列

1、基本内容

链式队列是以链表形式构成的队列数据结构。

链式队列的结构体如下:

typedef int data_t;
//链表
typedef struct node{
    data_t data;
    struct node* pNext;
}listnode,*linklist;
//队列
typedef struct{
    linklist front;//始终指向冗余的头
    linklist reat; //始终指向入队的位置,新数据接在rear后
}linkqueue;

入队与出队示意图: 

在链式队列中,fornt代表冗余的头,rear代表将要入队的位置。

  • 空队:当fornt、rear都指向冗余节点时,代表没有数据,即为空队
  • 入队:当想要入队时,只需要将数据链接到rear的位置之后即可。
  • 出队:当想要出队时,只需要把front后一个数据释放即可,当释放后为空时,需要将rear指向冗余的头。

链式队列代码的文件构成:

  • linkqueue.h:数据结构的定义、运算函数接口
  • linkqueue.c:运算函数接口的实现
  • test.c:使用数据结构实现的应用功能代码

链式队列相关函数: 

  • 创建:linkqueue* queue_create(void);
  • 删除:int queue_delete(linkqueue** pQueue);
  • 入队列:int enter_queue(linkqueue* pQueue,data_t value);
  • 出队列:int out_queue(linkqueue* pQueue,data_t* value)

2、功能实现

2.1 创建

创建链式队列,需要申请两个空间:冗余的头和队列。初始化时需要把front、rear指向冗余的头,代表这个队列为空队。

具体代码实现如下:

/*
 * queue_create:创建一个空队列
 * @ret  NULL--err  other--空队列指针
 * */
linkqueue* queue_create(void){

	linkqueue* pQueue = NULL;
	linklist pLink = NULL;

	//1.申请空间
	//1.1 队列空间
	pQueue = (linkqueue*)malloc(sizeof(linkqueue));
	if(pQueue == NULL){
		printf("pQueue malloc err\n");
		return NULL;
	}
	//1.2 单链表空间
	pLink = (linklist)malloc(sizeof(listnode));
	if(pLink == NULL){
		printf("pLink malloc err\n");
		free(pQueue);//释放前面申请的空间
		return NULL;
	}
	//2.初始化
	pLink->data = 0;
	pLink->pNext = NULL;
	pQueue->front = pLink;
	pQueue->rear = pLink;
	return pQueue;
}

2.2 删除

删除链式队列,首先需要释放单链表的空间,之后再释放队列的空间。

具体代码实现如下:

/*
 * queue_delete:删除整个队列
 * param pQueue:队列地址
 * @ret  -1--err  0--success
 * */
int queue_delete(linkqueue** pQueue){
	linklist pTmp = NULL;
	//1.判断参数有效性
	if(*pQueue == NULL){
		printf("pQueue is NULL\n");
		return -1;
	}
	//2.开始释放链表
	while((*pQueue)->front != NULL){
		pTmp = (*pQueue)->front;
		(*pQueue)->front = (*pQueue)->front->pNext;
		free(pTmp);
	}
	//3.释放队列
	free(*pQueue);
	*pQueue = NULL;
	return 0;
}

2.3 入队列

入队列的示意图如 "1、基本内容" 中所示,只需要将新数据链接到rear后即可,之后rear需要指向新数据。

具体代码实现如下:

/*
 * enter_queue:入队列
 * param pQueue:队列地址
 * param value:入队数据
 * @ret  -1--err  0--success
 * */
int enter_queue(linkqueue* pQueue,data_t value){
	linklist pLink = NULL;
	//1.判断参数有效性
	if(pQueue == NULL){
		printf("pQueue is NULL\n");
		return -1;
	}
	//2.创建链表结点
	pLink = (linklist)malloc(sizeof(listnode));
	if(pLink == NULL){
		printf("malloc err\n");
		return -1;
	}
	pLink->data = value;
	pLink->pNext = NULL;
	//3.入队列
	//rear后链接新结点
	pQueue->rear->pNext = pLink;
	//队列指针偏移
	pQueue->rear = pLink;
	return 0;
}

2.4 出队列

出队列的示意图如 "1、基本内容" 中所示,需要将front后一个数据进行释放,并连接上剩余的数据。

注意点1:当出队列后,队列为空队,这时需要将rear指向冗余的头

注意点2:出队列之前需要先判断队列是否为空

注意点3:出队之后,需要释放出队元素的空间

具体的代码实现如下:

/*
 * out_queue:出队列
 * param pQueue:队列地址
 * param value:出队数据存放的地址
 * @ret  -1--err  0--success
 * */
int out_queue(linkqueue* pQueue,data_t* value){
	linklist pTmp = NULL;
	//1.判断参数有效性
	if(pQueue == NULL){
		printf("pQueue is NULL\n");
		return -1;
	}
	//2.判断是否为空队列
	if(pQueue->front == pQueue->rear){
		printf("queue is empty\n");
		return -1;
	}
	//3.保存剩余数据
	pTmp = pQueue->front->pNext->pNext;
	//4.出队后队列为空时,需将rear指向冗余头部代表空队列
	if(pQueue->front->pNext == pQueue->rear){
		pQueue->rear = pQueue->front;
	}
	//5.开始出队列
	*value = pQueue->front->pNext->data;
	free(pQueue->front->pNext);
	pQueue->front->pNext = pTmp;
	return 0;
}

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

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

相关文章

springboot 整合quartz定时任务

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、pom的配置1.加注解 二、使用方法1.工程图2.创建工具类 三、controller 实现 前言 提示:这里可以添加本文要记录的大概内容: 提示&a…

微服务、云计算、分布式开发全套课程课件,来原于企培和多年大厂工作提炼

本课内容为笔者16年企业工作期间企培经验总结的 全套课件。需要自取,已分块和整体上传至资源下载中。 全部来源于笔者多年企业培训迭代整理,并做了特殊处理,所以内容无涉密和版权麻烦。 课件内容全部来源于笔者在京东、58、阿里;中…

第二百三十二节 JPA教程 - JPA教程 - JPA ID自动生成器示例、JPA ID生成策略示例

JPA教程 - JPA ID自动生成器示例 我们可以将id字段标记为自动生成的主键列。 数据库将在插入时自动为id字段生成一个值数据到表。 例子 下面的代码来自Person.java。 package cn.w3cschool.common;import javax.persistence.Entity; import javax.persistence.GeneratedValu…

java内存概述

运行时数据区域 Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启 动而一直存在,有些区域则是依赖用户线程的启动和结束而建立和…

charls基于夜神模拟器抓取安卓7.0应用程序https请求

charls基于夜神模拟器抓取安卓7.0应用程序https请求 1、安装charls(安装步骤这里就不详细说了)2、下载证书(证书后缀名 xx.pem)3、使用git bash生成证书hash4、上传证书到安卓的系统证书目录下(夜神模拟器方案&#xf…

C++速通LeetCode简单第9题-二叉树的最大深度

深度优先算法递归: /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right…

屏幕缺陷检测-目标检测数据集(包括VOC格式、YOLO格式)

屏幕缺陷检测-目标检测数据集(包括VOC格式、YOLO格式) 数据集: 链接:https://pan.baidu.com/s/1mb83CzAAOkvMZ_LS9Alt8w?pwdagi6 提取码:agi6 数据集信息介绍: 共有 3789 张图像和一一对应的标注文件 标…

RPC远程调用的序列化框架

序列化框架对比: 一、Java Serialiazer 字段serialVersionUID的作用是为了在序列化时保持版本的兼容性,即版本升级时反序列化仍保持对象的唯一性。 //序列化 ByteArrayOutputStream bout new ByteArrayOutputStream(); ObjectOutoutStream out new O…

【Kubernetes笔记】为什么DNS解析会超时?

【Kubernetes笔记】为什么DNS解析会超时? 目录 1 问题背景2 产生后续的问题3 DNS 负缓存工作原理:4 如何解决和缓解 DNS 负缓存 4.1 减小负缓存 TTL4.2 重试机制4.3 减少 Pod 的频繁重启或调度4.4 使用 Headless Service4.5 手动刷新 DNS 缓存 5 总结 …

苹果cms多语言插件,插件配置前端默认语言采集语言等

苹果CMS(maccmscn)是一款功能强大的内容管理系统,广泛应用于视频网站和其他内容发布平台。为了满足全球用户的需求,苹果CMS支持多语言插件,使得网站能够方便地提供多语言版本。以下是关于苹果CMS多语言插件的详细介绍&…

网络原理2-网络层与数据链路层

目录 网络层数据链路层 网络层 网络层做的工作: 1、地址管理–>IP地址 2、路由选择–>数据包传输的路径规划 网络层主要的协议就是IP协议 IP协议的报头结构: 4位版本: 有两个取值,4表示IPv4,6表示IPv6&am…

关于网站ERR_TOO_MANY_REDIRECTS错误的修改办法

今天网站因为证书到期,七牛云的报错一直ERR_TOO_MANY_REDIRECTS,302重定向次数过多了,连后台都进不去 多次清除cookie未果,终于找到了原因:设置了太多重定向, 1.http强制跳转 2.宝塔后台设置了跳转 3.域…

备战软考Day02-数据结构与算法

1.基本概念与三要素 1.什么是数据 数据是信息的载体,是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。数据是计算机程序加工的原料。 2.数据元素、数据项 数据元素是数据的基本单位,通常作为一个整体进行…

树莓派Pico2(RP2350)开发环境搭建

树莓派Pico2(RP2350)开发环境搭建 文章目录 树莓派Pico2(RP2350)开发环境搭建1、RP2350介绍2、开发环境搭建3、工程编译4、固件下载Raspberry Pi再次通过推出RP2350 MCU突破了微控制器设计的界限。这款微控制器是之前RP2040的重大升级,带来了更强大的性能、高级安全功能,…

基于SSM的二手车管理系统的设计与实现 (含源码+sql+视频导入教程)

👉文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1 、功能描述 基于SSM的二手车管理系统4拥有三种角色 管理员:订单管理、在售车辆管理、下架车辆管理、品牌管理、分类管理、推荐管理、统计等 商家:登录注册、添加/下架/删除车辆…

vscode搭建ros开发环境问题记录(更新...)

文章目录 vscode 不能自动补全 开发环境: vmware 15.7 ubuntu 20.04 ros noetic vscode 不能自动补全 这里将头文件已经正确包含到c_cpp_properties.json中代码中仍然不能自动补全, 将C_CPP插件设置中的Intelli Sense Engine 设置为TagParser,然后重新加…

828华为云征文 | 云服务器Flexus X实例:部署 Gitea,拥有自己的Git仓库,管理本地代码

目录 一、什么是 Gitea 二、安装 Docker 环境 2.1 更新 apt 软件源 2.2 安装依赖 2.3 安装 Docker 三、安装 Gitea 3.1 创建 docker-compose.yml 3.2 启动 Gitea 服务 3.3 初始化配置 四、运行 Gitea 4.1 登录/注册 4.2 创建仓库 五、总结 本篇文章通过部署 Gite…

【BFS专题】— 多源最短路问题

1、矩阵 - 力扣(LeetCode) 思路: 首先创建一个dist数组,将dist数组初始化为-1,表示该位置没有被搜索和记录该位置的值然后再遍历mat数组,将数组中的 0 添加到队列中,并且修改dist对应位置的值为…

全网最全最详细的跨域解决方案

你们好,我是金金金。 前置知识 本篇文章以通俗易懂的方式进行描述,自己组织语言进行输出,尽量让每一个人都能看得懂。哪里有说的不正确的地方 大佬请在评论区指正! 首先需要了解浏览器的同源策略 浏览器的同源策略 MDN解释地址&…

神经网络通俗理解学习笔记(3)注意力神经网络

Tansformer 什么是注意力机制注意力的计算键值对注意力和多头注意力自注意力机制注意力池化及代码实现Transformer模型Transformer代码实现 什么是注意力机制 注意力机制的发展史 Attention Mechanism Mnih V, Heess N, Graves A. Recurrent models of visual attention, 2014…