队列详解(C语言实现)

文章目录

  • 写在前面
  • [1 队列的定义](#1 队列的定义)
  • [2 队列的初始化](#2 队列的初始化)
  • [3 数据入队列](#3 数据入队列)
  • [4 数据出队列](#4 数据出队列)
  • [5 获取队头元素](#5 获取队头元素)
  • [6 获取队尾元素](#6 获取队尾元素)
  • [7 获取队列元素个数](#7 获取队列元素个数)
  • [8 判断队列是否为空](#8 判断队列是否为空)
  • [8 队列的销毁](#8 队列的销毁)

写在前面

本片文章详细介绍了另外两种存储逻辑关系为 "一对一" 的数据结构------栈和队列中的队列,并使用C语言实现链队列。

队列C语言实现源码:队列源码

以队列在存储数据时具有特殊的顺序规则:
队列 :使用队列存储数据,遵循 "先进先出 " 的原则,即最先进队列的数据最先出队列。队列也可以分为顺序队列(基于数组实现)和链队列(基于链表实现)。

队列的实现方式分为顺序和链式结构,分别适用于不同的场景。顺序结构在内存中占据一块连续的空间,而链式结构通过节点之间的指针连接。这使得栈和队列在实际应用中更灵活,可以根据具体需求选择不同的实现方式。

1 队列的定义

链式队列的实现其实和之前单链表的实现很类似,只不过队列中数据的进出要遵循 "先进先出" 的原则。
链式队列节点的定义:

c 复制代码
typedef int QDataType;

typedef struct QueueNode
{
	QDataType val;
	struct QueueNode* next;
}QNode;

队列的定义通常包括两个指针和一个整型,一个指针front指向队列的头,一个指针tail指向队列的尾,还有一个整型size用来记录队列的数据个数。
下面是队列结构的定义:

c 复制代码
typedef struct Queue
{
	QNode* front;//指向队列头部的指针
	QNode* tail;//指向队列尾部的指针
	int size;//记录队列中元素个数
}Queue;

2 队列的初始化

刚开始队列为空,头指针front和尾指针tail指向NULL,此时队列中元素个数为0,因此将size初始化为0。

代码如下:

c 复制代码
void QueueInit(Queue* pq)
{
	assert(pq);//检查参数有效性

	pq->front = pq->tail = NULL;
	pq->size = 0;
}

3 数据入队列

数据入队列分为一下两种情况:

  1. 队列为空时,新建节点,并用要入队列的数据初始化节点,此时front 和 tail都指向新插入的节点,同时将size+1。
  2. 队列不为空时,新建节点,并用要入队列的数据初始化节点,此时tail->next指向新插入的节点,更新tail指向新插入的节点。

数据1 2 3 4 入队列图解:

代码如下:

c 复制代码
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);//检查参数有效性
	//创建新节点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("QueuePush->malloc");
		exit(-1);
	}
	newnode->next = NULL;
	newnode->val = x;
	//入队列
	//1. 队列为空
	//2. 队列不为空
	if (pq->front == NULL)
	{
		assert(!pq->tail);// 队列为空时,tail front都为空
		pq->front = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}

4 数据出队列

我们知道,队列只能在队尾一端入数据,出数据时只能出队头的数据。因为它要保证有数据元素需要出队时,按照 "先进先出" 的原则。

数据出队的步骤如下:

  1. 在执行数据出队列操作之前,需要检查队列是否为空。如果队列为空(即没有数据),则无法执行出队列操作。
  2. 如果队列不为空,即存在数据,就可以执行出队列操作。
    此时数据出队列又分为两种情况:
    • 队列中只有一个数据:
      此时只需要将该数据所在节点释放,并将 front 和 tail 置为NULL即可。
    • 队列中有两个及以上数据:
      保存头节点下一个节点的地址,释放头节点,更新front,使front指向新的队头元素。

数据1 2 3 4 出队列图解:

代码如下:

c 复制代码
void QueuePop(Queue* pq)
{
	assert(pq);//检查参数有效性
	assert(!QueueEmpty(pq));//检查队列是否为空,为空不能pop

	//出队列
	//1. 队列只有1个元素
	//2.队列有2个以上元素
	if (pq->front->next == NULL)
	{
		free(pq->front);
		pq->front = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->front->next;
		free(pq->front);
		pq->front = next;
	}
	pq->size--;
}

5 获取队头元素

获取队头元素的步骤如下:

  1. 在执行取队头元素操作之前,需要检查队列是否为空。如果队列为空(即没有数据),则无法执行此操作。
  2. 头指针front指向的就是队头元素,如要获取队头元素,因此只需返回front->val即可。

代码如下:

c 复制代码
QDataType QueueFront(Queue* pq)
{
	assert(pq);//检查参数有效性
	assert(!QueueEmpty(pq));//检查队列是否为空,为空不能取队头元素

	return pq->front->val;
}

6 获取队尾元素

获取队尾元素的步骤如下:

  1. 在执行取队尾元素操作之前,需要检查队列是否为空。如果队列为空(即没有数据),则无法执行此操作。
  2. 尾指针tail指向的就是队头元素,如要获取队尾元素,因此只需返回tail->val即可。

代码如下:

c 复制代码
QDataType QueueBack(Queue* pq)
{
	assert(pq);//检查参数有效性
	assert(!QueueEmpty(pq));//检查队列是否为空,为空不能取队尾元素

	return pq->tail->val;
}

7 获取队列元素个数

队列中的size记录的就是队列中元素的个数,如要获取队列元素个数,返回size即可。

代码如下:

c 复制代码
int QueueSize(Queue* pq)
{
	assert(pq);//检查参数有效性

	return pq->size;
}

8 判断队列是否为空

根据队列初始化函数,我们知道,队列为空时,front 和 tail 都指向NULL。

此时size=0,也可以用size来判断,这里作者选择用front 和 tail 来进行判断。

代码如下:

c 复制代码
bool QueueEmpty(Queue* pq)
{
	assert(pq);//检查参数有效性
	return pq->front == NULL && pq->tail == NULL;
}

8 队列的销毁

链队列用来存储数据的节点都是动态申请的,因此队列销毁时,只需要遍历该链队列,依次释放每个节点。最后将 front 和 tail 置为NULL,size 置为0即可。

代码如下:

c 复制代码
void QueueDestroy(Queue* pq)
{
	assert(pq);//检查参数有效性
	QNode* cur = pq->front;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	pq->front = pq->tail = NULL;
	pq->size = 0;
}

至此,本片文章就结束了,若本篇内容对您有所帮助,请三连点赞,关注,收藏支持下。

创作不易,白嫖不好,各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

如果本篇博客有任何错误,请批评指教,不胜感激 !!!

相关推荐
小牛itbull9 分钟前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
请叫我欧皇i18 分钟前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
闲暇部落21 分钟前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
GIS瞧葩菜30 分钟前
局部修改3dtiles子模型的位置。
开发语言·javascript·ecmascript
chnming198735 分钟前
STL关联式容器之set
开发语言·c++
带多刺的玫瑰38 分钟前
Leecode刷题C语言之统计不是特殊数字的数字数量
java·c语言·算法
熬夜学编程的小王1 小时前
【C++篇】深度解析 C++ List 容器:底层设计与实现揭秘
开发语言·数据结构·c++·stl·list
GIS 数据栈1 小时前
每日一书 《基于ArcGIS的Python编程秘笈》
开发语言·python·arcgis
Mr.131 小时前
什么是 C++ 中的初始化列表?它的作用是什么?初始化列表和在构造函数体内赋值有什么区别?
开发语言·c++
阿史大杯茶1 小时前
AtCoder Beginner Contest 381(ABCDEF 题)视频讲解
数据结构·c++·算法