【脚踢数据结构】队列(顺序和链式)

news2024/11/25 13:54:33
  • (꒪ꇴ꒪ ),Hello我是祐言QAQ
  • 我的博客主页:C/C++语言,Linux基础,ARM开发板,软件配置等领域博主🌍
  • 快上🚘,一起学习,让我们成为一个强大的攻城狮!
  • 送给自己和读者的一句鸡汤🤔:集中起来的意志可以击穿顽石!
  • 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏


        在我们的日常生活中,队列是一个非常常见的现象。无论是在商店结账,还是在公交站等车,我们都在使用队列。在计算机科学中,队列也是一个重要的数据结构,用于处理和组织数据。在这篇文章中,我们将详细探讨队列的定义、操作、以及如何用C语言实现队列。

一、队列的定义


        队列(Queue)是一种特殊类型的线性数据结构,它遵循特定的操作规则,即遵循“先进先出”(FIFO,First-In-First-Out)原则。这意味着在队列中,首先加入的元素将会首先被移除,最后加入的元素将会最后被移除。

         当我们想存入1时,先移动front(队头)然后再写入数据1,拿数据也是一样,但务必保证先移动rear(队尾),再拿出数据,否则将会错位导致出错。

二、顺序队列

      1.  队列结构体定义


        首先需要定义一个顺序队列,我们可以使用结构体来定义一个队列,它包含一个数组(用于存储队列的数据)和三个整数(用于表示队列长度、队首和队尾的位置)。


typedef int Datatype;

//队列的结构体定义
typedef struct Quene
{
	Datatype *q;	//用来存放队列的数据
	int size;		//队列的长度
	int front;		//队头
	int rear;		//队尾
}queue;

    2.  初始化队列


        接下来,我们需要初始化队列。在初始化时,我们将队首和队尾都设置为0,表示队列为空。

//初始化一个队列
queue *init_queue(int size)
{
	queue *que = malloc(sizeof(queue));
	if (que!=NULL)
	{
		que->q = calloc(size, sizeof(Datatype));
		que->size = size;
		que->front = 0;
		que->rear = 0;
	}
	return que;
}

    3.  队空和队满


        如果我们想要实现入队和出队操作,我们需要先考虑队列可能会溢出或下溢的情况,因此我们需要判断是否队空或队满。

//队空判断
bool isempty_queue(queue *q)
{
	return (q->rear == q->front);
}

//队满判断
bool isfull_queue(queue *q)
{
	return ((q->rear+1)%q->size == q->front);
}

    4.  入队和出队

//入队
bool en_queue(queue *que, Datatype data)
{
	if (isfull_queue(que))
	{
		return false;
	}
	//先挪rear
	que->rear = (que->rear+1)%(que->size);
	//再入数据
	que->q[que->rear] = data;
	return true;
}

//出队
bool de_queue(queue *que, Datatype *data)
{
	if (isempty_queue(que))
	{
		return false;
	}
	//先挪front
	que->front = (que->front+1)%(que->size);
	//再取数据
	*data = que->q[que->front];
	return true;
}


        队列是计算机科学中的一个基础概念,它在许多场景中都有应用,如操作系统的任务调度,网络的数据包处理等。理解队列的工作原理并能够实现队列,对于学习和理解计算机科学的其他概念是非常有帮助的。希望这篇文章能帮助你理解和实现队列。

        下面是一个简单的顺序队列举例,实现:输入正整数,添加员工信息,入队,用这个正整数表示员工号;输入负整数,出队(队首),显示该员工的所有信息;否则就退出。

        员工信息:工号、姓名、工资

        完整源码:

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

#define SIZE 1024
typedef struct people
{
	int number;		//工号
	char name[20];	//姓名
	int money;		//工资
}Datatype;

//队列的结构体定义
typedef struct Quene
{
	Datatype *q;	//用来存放队列的数据
	int size;		//队列的长度
	int front;		//队头
	int rear;		//队尾
}queue;

//初始化一个队列
queue *init_queue(int size)
{
	queue *que = malloc(sizeof(queue));
	if (que!=NULL)
	{
		que->q = calloc(size, sizeof(Datatype));
		que->size = size;
		que->front = 0;
		que->rear = 0;
	}
	return que;
}

//队空判断
bool isempty_queue(queue *q)
{
	return (q->rear == q->front);
}

//队满判断
bool isfull_queue(queue *q)
{
	return ((q->rear+1)%q->size == q->front);
}

//入队
bool en_queue(queue *que, Datatype data)
{
	if (isfull_queue(que))
	{
		return false;
	}
	//先挪rear
	que->rear = (que->rear+1)%(que->size);
	//再入数据
	que->q[que->rear] = data;
	return true;
}

//出队
bool de_queue(queue *que, Datatype *data)
{
	if (isempty_queue(que))
	{
		return false;
	}
	//先挪front
	que->front = (que->front+1)%(que->size);
	//再取数据
	*data = que->q[que->front];
	return true;
}

// 添加信息
void init_info(Datatype *data,int n)
{
	data->number = n;
	printf("请输入工人信息\n");
	while(getchar() != '\n');
	printf("姓名:");
	scanf("%s", data->name);
	printf("工资:");
	scanf("%d", &data->money);
}

int main(int argc, char const *argv[]) {

    queue *q = init_queue(SIZE);
    int n;
    Datatype data;
    

    while (1) 
	{
		printf("请输入一个正整数或负数\n");
		scanf("%d", &n);
		
		if (n > 0){
			init_info(&data, n);
			en_queue(q, data);
			continue;
		}
		else if(n < 0){
			Datatype d;
			if (de_queue(q, &d)) {
				printf("工号:%d,姓名:%s,工资:%d\n", d.number, d.name, d.money);
			} else {
				printf("队列已空,无法出队。\n");
			}
		}
		else{
			return -1;
		}
	}
    free(q->q);
    free(q);

    return 0;
}

三、链式队列

        链式队列(Linked Queue)是一种使用链表来实现的队列数据结构。与顺序队列不同,链式队列的元素并不直接存储在数组中,而是通过链表节点来连接。

        并且 由于使用链表实现,链式队列的大小可以根据需要动态分配和释放内存,避免了固定数组大小可能带来的限制。因此就没有是否队满问题

1.结构体定义

typedef int Datatype;

typedef struct Node
{
	Datatype data;
	struct Node *next;
}node;

typedef struct List_queue
{
	node *rear;		//队尾指针
	node *front;	//队头指针
	int size;		//链式队列的长度(实际的元素的个数)
}L_q;

2.创建新节点和判断队空

//创建新节点
node *create_node(Datatype data)
{
	node *new = malloc(sizeof(node));
	if (new != NULL)
	{
		new->data = data;
		new->next = NULL;
	}
	return new;
}
//链式队列是否为空
bool isempty_list_queue(L_q *q)
{
	return (q->size == 0);
}

3.初始化队列

//初始化链式队列
L_q *init_list_queue()
{
	L_q *q = malloc(sizeof(L_q));
	if (q!=NULL)
	{
		q->rear = NULL;
		q->front = NULL;
		q->size = 0;
	}
	return q;
}

3.入队

        入队操作在链表的末尾添加一个新节点,同时更新队尾指针。

//入队
bool en_list_queue(L_q *q, Datatype data)
{
	//先要将数据创建新节点
	node *new = create_node(data);
	if (new==NULL)
	{
		return false;
	}
	//如果是第一次入队,new节点既是队尾,也是队头
	if (isempty_list_queue(q))
	{
		q->rear = new;
		q->front = new;
	}
	else    //不是第一次入队
	{
		//先将尾部节点的next指向new节点
		q->rear->next = new;
		//尾部节点要变成新节点new
		q->rear = new;
	}
	//队的元素个数要+1
	q->size++;
	return true;
}

4.出队

         出队操作移除链表的第一个节点,同时更新队头指针。

//出队
bool de_list_queue(L_q *q, Datatype *data)
{
	if (isempty_list_queue(q))
	{
		return false;
	}
	else if(q->size == 1)//只有一个数据的时候
	{
		q->rear = NULL;
	}
	//在链表不为空的情况下,先拿队头的数据
	*data = q->front->data;
	//将队头指向下一个节点
	q->front = q->front->next;
	//链式队列的元素个数-1
	q->size--;
	return true;
}

 5.遍历

//遍历
void display(L_q *q)
{
	if (q->front == NULL)
	{
		return ;
	}
	node *p = q->front;
	while(p->next != NULL)
	{
		printf("%d ", p->data);
		p = p->next;
	}
	printf("%d\n", p->data);
}

        简单示例:当我们输入正数时,入队并遍历整个队列;当我们输入负数时,出队一个元素,并再次遍历队列;输入0时退出。

int main(int argc, char const *argv[])
{
	L_q *q = init_list_queue();
	int num;
	Datatype data;
	while(1)
	{
		scanf("%d", &num);
		if(num > 0)
		{
			en_list_queue(q, num);	
			display(q);	
		}
		else if(num < 0)
		{
			de_list_queue(q, &data);
			display(q);	
		}
		else
		{
			break;
		}
	}
	return 0;
}

四、结语

        
        队列作为一种基本的数据结构,在我们的编程生涯中扮演着重要的角色。希望这篇文章提供了一个清晰、详细的队列概述,帮助你理解队列的基本概念和操作,以及如何用C语言实现队列。

        选择顺序队列还是链式队列取决于实际应用的需求。如果你需要一个固定大小的队列,可以考虑使用顺序队列。如果你希望队列大小能够根据需要进行动态调整,那么链式队列更适合。在大多数情况下,链式队列具有更好的扩展性和灵活性。

        更多C语言Linux系统ARM板实战数据结构相关文章,关注专栏:

   手撕C语言

            玩转linux

                    脚踢数据结构

                            6818(ARM)开发板实战

📢写在最后

  • 今天的分享就到这啦~
  • 觉得博主写的还不错的烦劳 一键三连喔~
  • 🎉感谢关注🎉

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

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

相关文章

JVM内存区域

预备 为了更好的理解类加载和垃圾回收&#xff0c;先要了解一下JVM的内存区域&#xff08;如果没有特殊说明&#xff0c;都是针对的是 HotSpot 虚拟机。&#xff09;。 Java 源代码文件经过编译器编译后生成字节码文件&#xff0c;然后交给 JVM 的类加载器&#xff0c;加载完…

揭秘内存暴涨:解决大模型分布式训练OOM纪实

在现代深度学习开发中&#xff0c;我们通常依赖其他模块&#xff0c;像搭积木一样构建复杂的软件系统&#xff0c;这个过程往往快速且有效。然而&#xff0c;如何在遇到问题时迅速定位和解决问题&#xff0c;由于系统的复杂性和耦合性&#xff0c;一直困扰着深度学习系统设计和…

UTONMOS:元宇宙在网络游戏领域得到充分运用

元宇宙到底是个啥&#xff1f;这个词大概意思应该就是人类能从真实世界进入一个虚拟世界体验另一种生活&#xff0c;这个虚拟的世界就叫“元宇宙”。 从科幻走入现实&#xff0c;元宇宙究竟有什么用途&#xff1f;它离我们到底还有多远&#xff1f;又将给我们的生活带来哪些变…

htmlCSS-----高级选择器

目录 前言 伪类选择器 状态类 结构类 伪元素选择器 属性选择器 前言 前面我们学习了CSS中的相关选择器&#xff08;链接html&CSS-----CSS选择器&#xff08;上&#xff09;_灰勒塔德的博客-CSDN博客 html&CSS-----CSS选择器&#xff08;下&#xff09;_灰勒塔…

【Linux】线程的互斥

目录 写在前面的话 相关背景概念 什么是互斥 互斥锁&#xff08;互斥量&#xff09; 互斥锁的使用 一些相关的问题 线程安全和可重入的区别 写在前面的话 本文章主要介绍了线程的互斥的相关内容&#xff0c;而且本文的概念也比较多&#xff0c;所以需要有一些前提知识作…

【ES6】深入理解ES6(1)

一、块级作用域绑定 var声明及变量提升机制 二、字符串和正则表达式 字符串&#xff08;String&#xff09;是JavaScript6大原始数据类型。其他几个分别是Boolean、Null、Undefined、Number、Symbol&#xff08;es6新增&#xff09;。 更好的Unicode支持 1. UTF-16码位 字…

23款奔驰AMG GT50更换原厂运动排气系统,战斗感立马提升了

改装运动排气&#xff0c;原车中控的按键组也是需要更换的。与原车按键相比&#xff0c;只是多了一个排气的控制按键&#xff0c;也正是这个按键&#xff0c;能让车辆可静可怒&#xff0c;安静与怒吼就在一键之间。

QT-图标绘画工具

QT-图标绘画工具 一、效果演示二、关键程序三、程序链接 一、效果演示 二、关键程序 代码如下&#xff1a; #include "DrawDialogFactory.hpp" #include "DrawDialog.hpp" #include "GlobalDrawProperties.hpp"#include "Shape.hpp"…

pnpm常用命令

pnpm常用命令 下载pnpm&#xff0c;但是出现了 npm WARN notsup Unsupported engine for pnpm8.6.12: wanted: {"node":">16.14"} (current: {"node":"14.15.0","npm":"6.14.8"}) npm WARN notsup Not compa…

ViewUI表格Table嵌套From表单-动态校验数据合法性的解决方法

项目场景&#xff1a; 项目需求&#xff1a;在表格中实现动态加减数据&#xff0c;并且每行表格内的输入框&#xff0c;都要动态校验数据&#xff0c;校验不通过&#xff0c;不让提交数据&#xff0c;并且由于表格内部空间较小&#xff0c;我仅保留红边框提示&#xff0c;文字…

【编程指南】ES2016到ES2023新特性解析一网打尽

ES2016 Array.prototype.includes() Array.prototype.includes 方法&#xff1a; 这个方法用于检查数组是否包含特定元素&#xff0c;如果包含则返回 true&#xff0c;否则返回 false // 我有一个水果篮子 const fruitBasket [apple, banana, orange, grape];// 我要检查篮…

关于pycharm安装出现的interpreter field is empty,无法创建项目存储位置

关于pycharm安装出现的interpreter field is empty&#xff08;解释器为空&#xff09; 关于pycharm安装出现的interpreter field is empty&#xff0c;无法创建项目存储的位置。如图&#xff1a; 我之前安装的时候一直老是有这个提示&#xff0c;后来才发现是因为没安装这个p…

腾讯云服务器轻量和CVM有什么区别?

腾讯云轻量服务器和云服务器有什么区别&#xff1f;为什么轻量应用服务器价格便宜&#xff1f;是因为轻量服务器CPU内存性能比云服务器CVM性能差吗&#xff1f;轻量应用服务器适合中小企业或个人开发者搭建企业官网、博客论坛、微信小程序或开发测试环境&#xff0c;云服务器CV…

linux 安装go 1.18版本

首先去官网找到对应的版本 直接下载下来&#xff08;如果服务器可以直接访问到go 官网也可以wget直接下载到服务器&#xff09; 然后把该包上传到linux 的/usr/local 目录下 然后直接解压安装该包&#xff1a; sudo tar -C /usr/local -zxvf go1.18.10.linux-amd64.tar.gz 然…

通过Statement静态语句,实现CRUD操作

首先你需要创建 数据库 和 s_students学生表&#xff0c;再进行下一步的 增&#xff08;add&#xff09;&#xff0c;删(del)&#xff0c;改(update)&#xff0c;查(query)。 查询所有学生姓名&#xff1a; Testvoid query(){try{Statement st conn.createStatement();ResultS…

利用Torchmetrics库快速进行Torch的评价指标计算(推荐)

目录 1、安装 2、基本流程介绍 3、MetricCollection 4、自定义指标 5、我们可以调用多个指标计算不同的任务 6、可以是标签,也可以是one_hot编码 7、常用分类指标计算 8、异常报错 1、安装 官网地址:Welcome to TorchMetrics — PyTorch-Metrics 1.0.1 documenta…

JUL 日志 - 最简单易用的Java日志框架

在正式的生产环境下是不能使用 System.out 进行日志记录的 因为 System.out 不能提供时间、线程、执行过程 等信息&#xff0c;如果要手动打印输出则会非常麻烦 而日志就帮我们把这些事给干了 接下来我们学一个最简单的日志框架 JUL JUL全称Java util Logging是java原生的日志框…

用户数据报协议UDP

UDP的格式 载荷存放的是:应用层完整的UDP数据报 报头结构: 源端口号:发出的信息的来源端口目的端口号:信息要到达的目的端口UDP长度:2个字节(16位),即UDP总长度为:2^16bit 2^10bit * 2^6bit 1KB * 64 64KB.所以一个UDP的最大长度为64KBUDP校验和:网络的传输并非稳定传输,…

资源限制类题目解法,看这一篇就够了!

算法拾遗三十七资源限制类题目 资源限制技巧汇总32位无符号整数的范围是0~4,294,967,295&#xff0c;现在有一个正好包含40亿个无符号整数的文件&#xff0c;可以使用最多1GB的内存&#xff0c;怎么找到出现次数最多的数32位无符号整数的范围是0~4294967295&#xff0c;现在又一…

【VBA入门】WorkBook 对象 Name操作 宏录制筛选删除代码

VBA 入门 问题记录1 了解Excel工作簿、表格关系1 默认新建WorkBook2 新建WorkBook并命名工作表添加数据3新建带有指定数量工作表的工作簿 ActiveWorkbook.Names用法(1) 创建名称 (全局名称和局部名称&#xff09; 宏录制验证删除可行性大招&#xff01;&#xff01;&#xff01…