C语言数据结构(6)——队列

news2025/1/15 22:34:42

欢迎来到博主的专栏——C语言进阶指南
博主ID:代码小豪

文章目录

    • 队列
    • 顺序结构的队列
      • 顺序队列的初始化
      • 顺序队列的入队列操作
      • 判断队列是否为空
      • 顺序队列的出队列操作
      • 顺序队列操作的所有代码
    • 链式结构的队列
      • 链式队列的初始化
      • 链式队列的初始化
      • 链式队列的入队列操作
      • 链式队列的出队列的操作
    • 链式队列的所有代码

队列

队列也是一种特殊的线性表,与栈先进后出(First In Last Out)的特性不同,队列的特性是先进先出(Firsr In First Out),即在表尾插入数据,在表头删除数据。

向队列插入数据的操作叫做入队列在这里插入图片描述
向队列删除数据的操作叫做出队列

在这里插入图片描述

当数据出队列时,处于队头的元素被删除,队头的后继元素成为新的队头
当数据入队列时,将新数据插入队尾元素的后继元素,并将新数据成队尾

队列的物理存储结构可以分为两种:

一是顺序存储结构的队列,即以数组的形式实现的队列

二是链式存储结构的队列,即以链表的形式实现的队列

通常来说,链式存储结构的队列性能更好,适用性也更佳

顺序结构的队列

顺序结构的队列分为两种,一种是使用静态开辟的空间的队列,称为静态队列
静态队列的结构类型为:

#define MAXSIZE 10
typedef int QueueData;
typedef struct queue
{
	QueueData vals[MAXSIZE];
	int front;
	int rear;
};

静态队列的缺点很明显,那就是队列会出现满的情况,在这种情况下无法进行入队列的操作。

动态队列主要作用就是可以对队列进行扩容,当队列出现满队列的状况时,可以对队列进行操作。

动态队列的结构如下:

#define MAXSIZE 10
typedef int QueueData;
typedef struct queue
{
	QueueData* vals;
	int front;
	int rear;
	int capacity;
}queue;

顺序队列的初始化

将队列中的数据根据需要进行初始化。

void SeqQueueInit(queue* q1)
{
	q1->vals = NULL;
	q1->front = 0;
	q1->rear = 0;
	q1->capacity = 0;
}

顺序队列的入队列操作

将待入队的数据插入至队尾(rear)当中,并将队尾(rear)指向下一个待插入数据的空间位置

在这里插入图片描述

void SeqQueuePush(queue* q1, QueueData e)
{
	if (SeqQueueFull(q1))//判断队列是否满
	{
		//满则进行扩容
		int newcapacity = q1->capacity == 0 ? 4 : 2 * q1->capacity;
		QueueData* tmp = (QueueData*)realloc(q1->vals,sizeof(QueueData) * newcapacity);
		assert(tmp);
		q1->vals = tmp;
		q1->capacity = newcapacity;
	}
	q1->vals[q1->rear] = e;
	q1->rear++;
}

判断队列是否为空

队列为空的情况很简单,当rear和front相等的时候队列为空
在这里插入图片描述

bool SeqQueueEmpty(queue* q1)
{
	return q1->front == q1->rear;
}

顺序队列的出队列操作

当数据出队列后,front需要指向新的队头元素,完成这个要求的方法有两种。
(1)当队头元素出队列后,将front的指针指向下一个元素

在这里插入图片描述
这种方法会导致队列的部分空间被浪费掉。
(2)
将队列的队头的位置保持不变,将后面的所有元素向前移动一位
在这里插入图片描述
这种处理方法虽然没有浪费空间,但是可以发现删除数据的时间复杂度到了O(N),也是存在不小的缺点

void SeqQueuePop(queue* q1)//方法1
{
	if (SeqQueueEmpty(q1))
	{
		perror("Queue is empty\n");
		exit(1);
	}
	q1->front++;
}

顺序队列操作的所有代码

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

#define MAXSIZE 10
typedef int QueueData;
typedef struct queue
{
	QueueData* vals;
	int front;
	int rear;
	int capacity;
}queue;

void SeqQueueInit(queue* q1);
void SeqQueueDestory(queue* q1);

void SeqQueuePush(queue* q1,QueueData e);
void SeqQueuePop(queue* q1);

QueueData SeqQueueFront(queue* q1);
bool SeqQueueEmpty(queue* q1);
bool SeqQueueFull(queue* q1);

void SeqQueueInit(queue* q1)
{
	q1->vals = NULL;
	q1->front = 0;
	q1->rear = 0;
	q1->capacity = 0;
}
void SeqQueueDestory(queue* q1)
{
	free(q1->vals);
}

void SeqQueuePush(queue* q1, QueueData e)
{
	if (SeqQueueFull(q1))//判断队列是否满
	{
		//满则进行扩容
		int newcapacity = q1->capacity == 0 ? 4 : 2 * q1->capacity;
		QueueData* tmp = (QueueData*)realloc(q1->vals,sizeof(QueueData) * newcapacity);
		assert(tmp);
		q1->vals = tmp;
		q1->capacity = newcapacity;
	}
	q1->vals[q1->rear] = e;
	q1->rear++;
}
void SeqQueuePop(queue* q1)
{
	if (SeqQueueEmpty(q1))
	{
		perror("Queue is empty\n");
		exit(1);
	}
	q1->front++;
}

QueueData SeqQueueFront(queue* q1)
{
	if (SeqQueueEmpty(q1))
	{
		perror("Queue is empty\n");
		exit(1);
	}
	return q1->vals[q1->front];
}

bool SeqQueueEmpty(queue* q1)
{
	return q1->front == q1->rear;
}
bool SeqQueueFull(queue* q1)
{
	return q1->rear == q1->capacity;
}

链式结构的队列

既然顺序队列有着空间存储要求大,删除的时间复杂度高的缺点,那么链式结构饿的队列能不能解决这些问题呢?

链式队列的初始化

我们创建一个队列节点的结构,再创建一个队列的整体结构,将队列元素储存在节点当中。

typedef int LQueueData;
typedef struct QueueNode
{
	LQueueData val;
	struct QueueNode* next;
}QueueNode;

typedef struct ListQueue
{
	QueueNode* front;//指向队头
	QueueNode* rear;//指向队尾
	int size;//队列大小
}ListQueue;

链式队列的初始化

根据使用需求对队列中的元素进行初始化,当链式队列为空队列时,队头与队尾指针都应该置为NULL。

void ListQueueInit(ListQueue* lq)
{
	lq->front = NULL;
	lq->rear = NULL;
	lq->size = 0;
}

链式队列的入队列操作

用尾插法,在队尾结点插入一个新的节点。
在这里插入图片描述

void ListQueuePush(ListQueue* lq, LQueueData e)
{
	//生成新节点
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	newnode->val = e;
	newnode->next = NULL;
	if (ListQueueEmpty(lq))
	{
		lq->front = newnode;
		lq->rear = newnode;
		lq->size++;
		return;
	}
	//尾插法
	lq->rear->next = newnode;
	lq->rear = newnode;
	lq->size++;

}

链式队列的出队列的操作

将front指针指向的节点释放,并将front指针指向下一个节点的位置
在这里插入图片描述

void ListQueuePop(ListQueue* lq)
{
	if (ListQueueEmpty(lq))
	{
		perror("Queue is empty\n");
		exit(1);
	}
	QueueNode* del = lq->front;
	lq->front = lq->front->next;
	lq->size--;
	free(del);
}

链式队列的所有代码

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

typedef int LQueueData;
typedef struct QueueNode
{
	LQueueData val;
	struct QueueNode* next;
}QueueNode;

typedef struct ListQueue
{
	QueueNode* front;//指向队头
	QueueNode* rear;//指向队尾
	int size;//队列大小
}ListQueue;

void ListQueueInit(ListQueue* lq);
void ListQueueDestory(ListQueue* lq);

void ListQueuePush(ListQueue* lq,LQueueData e);
void ListQueuePop(ListQueue* lq);

bool ListQueueEmpty(ListQueue* lq);
LQueueData ListQueueFront(ListQueue* lq);

int ListQueueSize(ListQueue* lq);

void ListQueueInit(ListQueue* lq)
{
	lq->front = NULL;
	lq->rear = NULL;
	lq->size = 0;
}
void ListQueueDestory(ListQueue* lq)
{
	QueueNode* cur = lq->front;
	while (cur)
	{
		QueueNode* del = cur;
		cur = cur->next;
		free(del);
	}
}

void ListQueuePush(ListQueue* lq, LQueueData e)
{
	//生成新节点
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	newnode->val = e;
	newnode->next = NULL;
	if (ListQueueEmpty(lq))
	{
		lq->front = newnode;
		lq->rear = newnode;
		lq->size++;
		return;
	}
	//尾插法
	lq->rear->next = newnode;
	lq->rear = newnode;
	lq->size++;

}
void ListQueuePop(ListQueue* lq)
{
	if (ListQueueEmpty(lq))
	{
		perror("Queue is empty\n");
		exit(1);
	}
	QueueNode* del = lq->front;
	lq->front = lq->front->next;
	lq->size--;
	free(del);
}

bool ListQueueEmpty(ListQueue* lq)
{
	if (lq->front == NULL)
	{
		lq->rear = NULL;
		return true;
	}
	return false;
}
LQueueData ListQueueFront(ListQueue* lq)
{
	if (ListQueueEmpty(lq))
	{
		perror("Queue is empty\n");
		exit(1);
	}
	return lq->front->val;
}

int ListQueueSize(ListQueue* lq)
{
	return lq->size;
}

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

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

相关文章

Python读取.csv/.txt文件并画图

文章目录 读取.txt文件并画出每列数据读取.csv文件并画出每列数据python绘图的基本知识补充 读取.txt文件并画出每列数据 main.ipynb //注意文件类型为.ipynbimport matplotlib.pyplot as plt import numpy as npdata np.loadtxt(result.txt) fig plt.figure(dpi100,figsize…

TabLayout预览不了?

<TableLayoutandroid:layout_width"wrap_content"android:layout_height"wrap_content"/> 当然预览不了了&#xff0c;这其实不是我要的控件。 而实际需要的是TabLayout 不是TableLayout &#xff01;&#xff01;&#xff01; <com.google.an…

浅析extern关键字

C中extern关键字的使用 文章目录 C中extern关键字的使用前言正文1. C与C编译区别2. C调用C函数3. C中调用C函数 总结 前言 ​ C 是一种支持多范式的编程语言&#xff0c;它既可以实现面向对象的编程&#xff0c;也可以实现泛型编程和函数式编程。C 还具有与C语言的兼容性&…

2024.3.4 JAVA 复习

Java环境搭建 1、JDK和JRE的概述 JDK&#xff1a;Java开发工具包(Java Development Kit), 包含开发工具 和 JRE. 常用的开发工具: javac, java JRE&#xff1a;Java运行时环境(Java Runtime Environment), 包含运行Java程序时所需的核心类库和 JVM. 核心类库: java.lang, jav…

YTM32同步串行通信引擎SPI外设详解(slave part)

YTM32同步串行通信引擎SPI外设详解&#xff08;slave part&#xff09; 文章目录 YTM32同步串行通信引擎SPI外设详解&#xff08;slave part&#xff09;IntroductionPricinple & Mechinism引脚信号Slave从机工作模式发送/命令FIFO和接收FIFOMatch匹配接收功能硬件片选和内…

windows环境下编译调试x265工程

1、在具备visual studio软件情况下&#xff0c;源码和工具下载 下载x265源码&#xff1a;https://github.com/videolan/x265 下载cmake:https://cmake.org/download/ 2、生成x265的工程项目 在自己cmake目录下&#xff0c;找到cmake-gui.exe&#xff0c;安装目录的bin习&#x…

CC攻击的特征和防护措施

随着互联网的快速发展&#xff0c;网络攻击日益频繁。在目前的各种网络攻击中&#xff0c;CC攻击是一种常见的网络攻击手段之一。CC攻击&#xff08;也称为DDoS攻击&#xff09;是指通过大量请求或恶意流量向目标网站或服务器发送请求&#xff0c;以使其服务不可用。可能大家都…

【Leetcode每日一题】 前缀和 - 连续数组(难度⭐⭐)(30)

1. 题目解析 题目链接&#xff1a;525. 连续数组 这个问题的理解其实相当简单&#xff0c;只需看一下示例&#xff0c;基本就能明白其含义了。 核心在于计算题目所给数组是否存在连续子数组使得数组里头0和1的数量相同&#xff0c;存在返回连续子数组最长长度即可&#xff0c…

passwd: Authentication token manipulation error

passwd: Authentication token manipulation error 身份验证令牌操作错误。 可能原因&#xff1a; 1、密码文件无修改权限&#xff08;有i权限&#xff09; lsattr /etc/{passwd,shadow} 取消方法 chattr -i /etc/passwd chattr -i /etc/passwd 2、/文件系统无空间或者无inod…

哇!!!!这个个人博客好好看!!!

做一个个人博客第一步该怎么做&#xff1f; 好多零基础的同学们不知道怎么迈出第一步。 那么&#xff0c;就找一个现成的模板学一学呗&#xff0c;毕竟我们是高贵的Ctrl c v 工程师。 但是这样也有个问题&#xff0c;那就是&#xff0c;那些模板都&#xff0c;太&#xff01;…

文生视频Sora模型发布,是否引爆AI芯片热潮

文生视频Sora模型发布&#xff0c;是否引爆AI芯片热潮 1. 引言 在人工智能的历史长河中&#xff0c;每一次技术的飞跃都伴随着社会生产力的巨大变革。自2015年以来&#xff0c;深度学习技术的突破性进展&#xff0c;尤其是在自然语言处理、图像识别和机器学习等领域的成功应…

elementUI表单验证遇到的问题

1.同一个addForm表单&#xff0c;同样的验证规则&#xff0c;有的输入框在没填写时能够显示红色&#xff0c;有的却毫无反应 解决方案&#xff1a;去elementUI官网看了一下验证表单的规则及属性&#xff0c;第一句就写 Form 组件提供了表单验证的功能&#xff0c;只需要通过 r…

【北京迅为】《iTOP-3588开发板网络环境配置手册》第3章 开发板直连电脑配置方法(不能上外网)

RK3588是一款低功耗、高性能的处理器&#xff0c;适用于基于arm的PC和Edge计算设备、个人移动互联网设备等数字多媒体应用&#xff0c;RK3588支持8K视频编解码&#xff0c;内置GPU可以完全兼容OpenGLES 1.1、2.0和3.2。RK3588引入了新一代完全基于硬件的最大4800万像素ISP&…

(内含领书福利)实在智能联合浙江外国语学院、清华大学出版社发布新时代跨境电商教材。

近日&#xff0c;“新时代跨境电商新形态教材”系列图书之《数智电商 AIRPA实战教程》新书发布会在杭州成功举办。 这本教材深入浅出&#xff0c;全面讲解了如何用业界前沿AI、RPA技术打造电商行业广泛应用的各种数字员工。内容详实&#xff0c;场景丰富&#xff0c;有理论教学…

常见的验证码

一、短信验证码 前端&#xff1a; 用户填写手机号&#xff0c;点击按钮发送请求用户短信得到验证码后&#xff0c;用户填写表单提交 form 表单&#xff0c;进行验证 后台&#xff1a; 随机生成几位验证码并将生成时间、手机号、验证码存储起来&#xff0c;可以存到session、…

crossover2023激活码分享crossover免费升级2024 crossover24更新内容

CrossOver是一款功能强大的系统兼容软件&#xff0c;它能够让Mac和Linux用户在不安装Windows操作系统的情况下直接运行Windows应用程序。以下是关于CrossOver的更多信息&#xff1a; 一、工作原理 CrossOver的工作原理是通过在Mac或Linux系统上模拟Windows应用程序所需的运行…

工业深度学习异常缺陷检测实战

在工业生产过程中&#xff0c;由于现有技术、工作条件等因素的不足和局限性&#xff0c;极易影响制成品的质量。其中&#xff0c;表面缺陷是产品质量受到影响的最直观表现&#xff0c;因此&#xff0c;为了保证合格率和可靠的质量&#xff0c;必须进行产品表面缺陷检测。 “缺陷…

Jvm 虚拟机命令

Jps (查看正在运行的Java 进程) jps -q 只输出进程id、省略主类名称 -m 输出Jvm 进程启动时传递给主类main 函数参数 -l 输出主类全名称 -v 输出 Jvm 启动时的Jvm 参数 Jstat 查看 Jvm 统计信息 -class 监视类装载、卸载数量、总空间以及类装载所耗费的时间 -gc 监视 Java 堆…

倾斜三维模型转3dtiles重建顶层

背景 作为地理信息行业的公司,我们经常面临将倾斜三维模型转换成3D Tiles的挑战。当处理小数据量时,我们可能没有太大问题;但当数据量增大,尤其是超过50GB后,即使一些高配置的硬件也无法避免浏览模型时的卡顿和长时间加载。甚至浏览器会闪退。在这种情况下,重建倾斜三维…

聊天室项目

服务器 #include <myhead.h> #define SER_IP "192.168.122.39" #define SER_PORT 8888 typedef struct Node //链表存储客户端的所有信息 {struct sockaddr_in cin; //存储客户端的网络地址信息struct Node *next; }*List; typedef struct Message//消息结构…