数据结构C语言版 —— 队列+循环队列实现

news2024/11/24 14:34:46

文章目录

  • 队列
    • 1.概念
    • 2. 生活中队列应用
    • 3. 队列的实现
      • 初始化队列
      • 入队列
      • 出队列
      • 获取队头元素
      • 获取队尾元素
      • 获取队列中元素个数
      • 判断队列是否为空
      • 销毁队列
    • 2. 循环队列


队列

1.概念

和栈相反,队列(queue)是一种先进先出的线性表,它只允许在一端进行插入,而在另一端被删除。这和生活中的排队是类似的,最先排队的最先离开。在队列中运行被插入的一端叫做队尾,允许被删除的一端叫做队尾

在这里插入图片描述

2. 生活中队列应用

比如我们去银行办理业务的时候需要去抽号机器上取一个号码,这起始就是队列的应用。每当有一个人取号后机器就会把这个号码入队列进行排队。等窗口工作人员进行叫号办理业务。

在这里插入图片描述

3. 队列的实现

队列可以用数组或者链表实现,使用链表实现会更加合适一些,因为如果使用数组实现在出队的时候效率会比较低。

队列的定义

因为是链表实现所以还要定义一个节点结构体,队列的结构题包含两个指针一个队头指针和一个队尾指针

typedef int QDataType;

typedef struct QListNode {
	QDataType data;
	struct QListNode* next;//下一个节点
}QNode;

typedef struct Queue
{
	QNode* front;//队头
	QNode* rear;//队尾
}Queue;

// 初始化队列
void QueueInit(Queue* q);
// 动态申请节点
QNode* BuyQNode(QDataType data);
// 队尾入队列
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);

初始化队列

初始化队列比较简单,让队头和队尾指向NULL,因为此时队列里没有任何元素。

// 初始化队列
void QueueInit(Queue* q)
{
	assert(q);
	q->front = NULL;
	q->rear = NULL;
}

因为这是链表实现所以还要定义个动态申请节点的函数

// 动态申请节点
QNode* BuyQNode(QDataType data)
{
	QNode* node = (QNode*)(malloc(sizeof(QNode)));
	if (node == NULL)
	{
		printf("申请失败\n");
		exit(-1);
	}
	node->data = data;
	node->next = NULL;
	return node;
}

入队列

入队列需要考虑两种情况,第一种是队列为空的情况,队列为空要把队头和队尾指针都指向第一个元素,其他情况只需要把节点插入到队尾指针后面,再让对队尾指针往后走即可。

// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
	assert(q);
	QNode* node = BuyQNode(data);
	if (q->front == NULL)
	{
		q->front = node;
		q->rear = node;
	}
	else
	{
		q->rear->next = node;
		q->rear = q->rear->next;
	}
}

出队列

出队列要考虑到队列是否为空,为空是不能进行出队列操作的。出队列只需要让队头指针往后走,再释放队头节点。

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

	QNode* cur = q->front;
	q->front = q->front->next;
	free(cur);
}

获取队头元素

// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));

	return q->front->data;
}

获取队尾元素

// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(!QueueEmpty(q));

	return q->rear->data;
}

获取队列中元素个数

和链表求长度是一样的

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

	QNode* cur = q->front;
	int count = 0;
	while (cur != NULL)
	{
		count++;
		cur = cur->next;
	}
	
	return count;
}

判断队列是否为空

当队头指向NULL时说明队列为空

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

销毁队列

销毁队列遍历一边队列,把每个节点给释放掉。

// 销毁队列
void QueueDestroy(Queue* q)
{
	assert(q);
	QNode* cur = q->front;
	while (cur != NULL)
	{
		q->front = cur->next;
		free(cur);
		cur = q->front;
	}
	q->front = NULL;
	q->rear = NULL;
}

2. 循环队列

循环队列也是一种队列,再队列的顺序存储结构中,除了用一组连续的存储单元依次存放队头到队尾元素外,还需要两指针 front 和 rear 分别指向队头和队尾。

在这里插入图片描述

我们约定,初始化空队列时,让 front 和 rear 都赋为0,也就是指向数组的0下标。每当插入元素时尾指针加1,每当删除元素时头指针加1。

因为这时一个循环队列,当 f r o n t = = r e a r front == rear front==rear时,无法判断循环是满还是空。所以可以有两种选择,一种是做一个标记判断是否为满了,而是创建队列的时候多开一个空间,浪费掉这个空间方便判断。

我们采用第二种方式,约定 f r o n = = r e a r fron == rear fron==rear表示队列为空, r e a r + 1 = = f r o n rear+1 == fron rear+1==fron表示队列满了。

还有一个问题就是这是一个循环队列,当尾指针走到最后一个位置时如何走到下标为0的位置,我们可以巧妙的用一个公式,假设队列大小为 size。

头指针向后走: ( f r o n + 1 ) % s i z e (fron+1)\%size (fron+1)%size

尾指针向后走: ( r e a r + 1 ) % s i z e (rear + 1)\%size (rear+1)%size

在这里插入图片描述

代码实现

typedef struct {
    int* arr;
    int front;
    int rear;
    int size;//容量
} MyCircularQueue;

bool myCircularQueueIsEmpty(MyCircularQueue* obj);
bool myCircularQueueIsFull(MyCircularQueue* obj);
MyCircularQueue* QUeue(int k) {
    
    MyCircularQueue* obj = (MyCircularQueue*)(malloc(sizeof(MyCircularQueue)));

    //创建容量为k+1大小的队列,浪费1个空间
    obj->arr = (int*)(malloc(sizeof(int)*(k+1)));
    obj->front = 0;
    obj->rear = 0;
    obj->size = k+1;
    return obj;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
    if (myCircularQueueIsFull(obj) == true)
    {
        return false;//满了
    }
    else
    {
        obj->arr[obj->rear] = value;
        obj->rear = (obj->rear+1) % (obj->size);
        return true;
    }

    
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    else
    {
        obj->front = (obj->front+1) % (obj->size);
        return true;
    }
}

int myCircularQueueFront(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj) == true)
    {
        return -1;
    }
    return obj->arr[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) {
    if (myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    return (obj->rear == 0) ? (obj->arr[obj->size-1]) : (obj->arr[obj->rear-1]);
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    //约定 头位相遇就是空,尾+1是头就是满
    if (obj->front == obj->rear)
    {
        return true;
    }
    return false;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
    //约定 头位相遇就是空,尾+1是头就是满
    if (((obj->rear)+1)%obj->size == (obj->front))
    {
        return true;
    }
    return false;
}

void myCircularQueueFree(MyCircularQueue* obj) {
    free(obj->arr);
    obj->front = NULL;
    obj->rear = NULL;
    free(obj);
}

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

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

相关文章

C#-winform调用COM组件(COM组件由Qt开发)

一、场景介绍 在项目开发中,需要Qt与C#进行混合编程,完成项目开发。C#这边作为主框架,Qt负责编写插件,将功能模块通过COM组件的形式封装注册,再由C#调用、交互完成最终的项目。 程序开发环境: win10 64位 编译器: VS2017 Qt版本: Qt5.12.6 二、Qt封装COM组件 2.1 环境…

android flutter 安装

下载 flutter官网下载安装:https://flutter.dev/docs/development/tools/sdk/releases 将下载下来的zip安装包解压到想安装Flutter SDK的路径。注意,不要将flutter安装到需要一些高权限的路径,比如C:\Program Files\ 配置环境变量 添加fl…

案例教学 | 如何确定ADAMS简化模型的准确性,以及简化模型精度不够怎么办?

仿真建模过程中不可避免地对各种复杂元素进行简化处理。这种建模思路的终极目标是不牺牲仿真精度、还提升仿真效率。在Adams仿真建模过程中也有一些常见的简化方式,如非线性元素按线性建模、不考虑摩擦力、通过耦合约束等效传动关系等等。应用简化建模之前&#xff…

蓝桥杯有必要参赛吗?

昨天和群里的小伙伴在群里聊,有的小伙伴竟然说蓝桥杯一等奖没有含量,我也是醉了! 就像去年看了一个号主写的:研究生遍地都是! 放眼全国14亿人口,别说研究生了,本科生占比有多少? “蓝桥杯是我人生中得到…

多态性:中的向下转型,instanceof 操作符的使用

多态性:中的向下转型,instanceof 操作符的使用 每博一文案 都说树叶不是一天变黄的,人心也不是一天变凉的,每一个现在的自己,其实都是过去的自己拼凑的。 如今我们的气质里都藏着过去走过的路,看过的书和爱…

混合模式和预乘原理的理解

首先说到混合模式,简单理解,混合模式就是同一像素上有两个颜色需要混合成一个使用的模式。 这里的两个像素点,我们把原先已经存在的,也就是下面的像素点颜色定义为目标颜色。把新加上来的,也就是上面的像素点颜色定义为…

【Selenium IDE录制脚本】三分钟教会你安装Selenium IDE的安装及使用

目录 1、安装Selenium IDE 1.1、安装Firefox浏览器 1.2、安装selenium IDE 2、selenium的脚本录制 1、安装Selenium IDE 1.1、安装Firefox浏览器 因为selenium的不同版本对Firefox的支持不同,所以我们安装了Firefox之后,需要关闭他的自动更新 搜索&…

Python-Tinydb数据库详解

目录 数据库 Tinydb Tinydb 使用 安装 导入 创建数据库 创建 table 增 删 查 改 其他函数 示例 最后 数据库 数据库就是存储数据的的地方,现在我们生活中几乎每时每刻做的事可能都有它的作用。今天来介绍 Tinydb 数据库,它适合初学者&am…

设计模式概述之建造者模式(五)

常说的设计模式是23种设计模式,分为3大类: 创建型模式5种:工厂方法、抽象工厂、单例、建造者、原型 结构型模式7种:适配器、代理、桥接、装饰者、外观、享元、组合 行为型模式11种:模板方法、解释器、策略、观察者、…

【如意如意顺遂我意快快显灵】

文章目录 ● 【猿如意安装】 (基于Windows环境安装) ● 【猿如意首页】 ● 【猿如意效率工具】 ● 【猿如意开发工具】 ● 【猿如意教程文档】 ● 【猿如意一行代码】 ● 【猿如意ChatGPT】 ● 【Markdown笔记】 猿如意官网:猿…

【码极客精讲】二叉树

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点…

Linux yum 命令

yum( Yellow dog Updater, Modified)是一个在 Fedora 和 RedHat 以及 SUSE 中的 Shell 前端软件包管理器。 基于 RPM 包管理,能够从指定的服务器自动下载 RPM 包并且安装,可以自动处理依赖性关系,并且一次安装所有依赖…

Go 微服务开发框架 DMicro 的设计思路

Go 微服务开发框架 DMicro 的设计思路 DMicro 源码地址: Gitee:dmicro: dmicro是一个高效、可扩展且简单易用的微服务框架。包含drpc,dserver等 背景 DMicro 诞生的背景,是因为我写了 10 来年的 PHP,想在公司内部推广 Go, 公司内部的组件及 rpc 协议都…

Python:whl文件简介及实践

文章目录简介一、安装过程二、whl源地址推荐小结简介 WHL文件是以Wheel格式保存的Python安装包,Wheel是Python发行版的标准内置包格式。在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件,…

【视觉高级篇】27 # 如何实现简单的3D可视化图表:GitHub贡献图表的3D可视化?

说明 【跟月影学可视化】学习笔记。 第一步:准备要展现的数据 可以使用这个生成数据:https://github.com/sallar/github-contributions-api 这里直接使用月影大佬的github提交数据的数据即可 结构大致如下: 第二步:用 SpriteJS…

黑*头条_第6章_kafka及异步通知文章上下架

黑*头条_第6章_kafka及异步通知文章上下架 文章目录黑*头条_第6章_kafka及异步通知文章上下架1)自媒体文章上下架2)kafka概述3)kafka安装配置4)kafka入门5)kafka高可用设计5.1)集群5.2)备份机制(Replication)6)kafka生产者详解6.1)发送类型6.2)参数详解7)kafka消费者…

小林Coding阅读笔记:操作系统篇之硬件结构,CPU Cache一致性问题

前言 参考/导流: 小林coding-2.4 CPU 缓存一致性学习意义 底层基础知识,了解CPU执行过程,让上层编码有效并发控制底层设计思维(对比 MySQL的并发控制)、更好地去理解JUC的锁、volatile以及JMM架构层面的一致性保证问…

毕业设计 单片机便携式空气质量检测仪 - 物联网 嵌入式

文章目录0 前言1 简介2 主要器件3 实现效果4 设计原理5 部分核心代码5 最后0 前言 🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长…

51.`.format`字符串格式化—最适合小白的格式化笔记

51..format字符串格式化 文章目录51..format字符串格式化1.课题导入2.知识回顾3..format的基本用法3.1{}为空3.2 {}中有编号3.3 {}中有变量名4.浮点数的格式化5..format官方语法6. .format格式化语法总结7. 总结8.课堂练习1.课题导入 【描述】 用input函数输入你每个月的工资…

MySQL中WHERE后跟着N多个OR条件会怎样...

GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。作者:叶金荣文章来源:社区原创 可能会执行非常慢,线上生产环境千万别写出这种SQL ... 背景交…