数据结构——队列

发布于:2025-09-04 ⋅ 阅读:(15) ⋅ 点赞:(0)

1 队列的概念

队列是一种线性表,它只能在一端插入数据,在另一端删除数据,插入数据的那一端被称为队尾,删除数据的那一端被称为队头,队列遵循 “先进先出” 原则,也就是说,先进入队列的元素会优先出队
在这里插入图片描述

2 队列的结构

队列可以用链表和顺序表来实现,但是普通的队列一般通过链表来实现,因为链表插入删除较方便
由于队列的队头,队尾,元素个数都需要记录,所以队列的结构体如下:

typedef int QDataType;
//队列中的结点
typedef struct QueueNode
{
	QDataType val;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* phead; //队首指针
	QNode* ptail; //队尾指针
	int size; //队列元素个数
}Queue;

3 队列的操作

3.1 队列的初始化

初始化队列,只需要把头尾指针置为空,元素个数设置为 0 即可
在这里插入图片描述

代码实现

void QueueInit(Queue* q)
{
	assert(q);

	q->phead = NULL;
	q->ptail = NULL;
	q->size = 0;
}

3.2 入队

入队时要往队尾插入元素,由于是用单链表实现的队列,因此入队就是进行单链表尾插,在尾插时,可以使用带头结点或不带头结点的方式,这边使用的是不带头结点的方式

队列为空
在这里插入图片描述
队列不为空
在这里插入图片描述
代码实现

void QueuePush(Queue* q, QDataType val)
{
	assert(q);

	QNode* node = (QNode*)malloc(sizeof(QNode));
	if (!node)
	{
		perror("malloc");
		return;
	}
	node->next = NULL;
	node->val = val;

	if (q->phead == NULL) //链表为空
	{
		q->phead = node;
		q->ptail = node;
	}
	else //链表不为空
	{
		q->ptail->next = node;
		q->ptail = node;
	}

	q->size++;
}

3.3 出队

在实现出队操作时,由于队头是链表头,所以进行头删,若队列只剩下一个元素,则需要特殊处理

队列不止一个元素
在这里插入图片描述
队列只有一个元素
在这里插入图片描述
代码实现

void QueuePop(Queue* q)
{
	assert(q);
	assert(q->size > 0);

	if (q->phead->next == NULL) //只有一个结点
		q->ptail = NULL;

	QNode* cur = q->phead;
	q->phead = cur->next;
	free(cur);
	cur = NULL;
	q->size--;
}

3.4 获取队头元素

由于 phead 就指向了队头,所以获取队头元素直接使用 phead 即可
在这里插入图片描述

代码实现

QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(q->size > 0);

	return q->phead->val;
}

3.5 获取队尾元素

由于 ptail 指向了队尾,所以直接使用 ptail 就可以获取队尾元素
在这里插入图片描述

代码实现

QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(q->size > 0);

	return q->ptail->val;
}

3.6 获取队列中元素的个数

由于在队列的结构体 Queue 中,已经使用了 size 来记录元素的个数,所以直接返回 size 即可,若没有定义 size ,则需要遍历结点并计数,较为繁琐

代码实现

int QueueSize(Queue* q)
{
	assert(q);

	return q->size;
}

3.7 判空

检查队列元素个数 size 是否为 0 即可

代码实现

bool QueueEmpty(Queue* q)
{
	assert(q);

	return q->size == 0;
}

3.8 销毁队列

由于队列是使用单链表实现的,所以在销毁队列时,需要将单链表的结点一个个释放
在这里插入图片描述
代码实现

void QueueDestroy(Queue* q)
{
	assert(q);

	QNode* cur = q->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	q->phead = NULL;
	q->ptail = NULL;
	q->size = 0;
}

4 队列的整体实现

Queue.h

#pragma once
//结构体定义,函数声明
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

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

//避免二级指针和多个形参的问题
typedef struct Queue
{
	QNode* phead; //队首指针
	QNode* ptail; //队尾指针
	int size; //队列元素个数
}Queue;

//队列初始化
void QueueInit(Queue* q);

//入队
void QueuePush(Queue* q, QDataType val);

//出队
void QueuePop(Queue* q);

//获取队头元素
QDataType QueueFront(Queue* q);

//获取队尾元素
QDataType QueueBack(Queue* q);

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

//判空
bool QueueEmpty(Queue* q);

//销毁队列
void QueueDestroy(Queue* q);

Queue.c

//函数实现
#include "Queue.h"

//队列初始化
void QueueInit(Queue* q)
{
	assert(q);

	q->phead = NULL;
	q->ptail = NULL;
	q->size = 0;
}

//入队
void QueuePush(Queue* q, QDataType val)
{
	assert(q);

	QNode* node = (QNode*)malloc(sizeof(QNode));
	if (!node)
	{
		perror("malloc");
		return;
	}
	node->next = NULL;
	node->val = val;

	if (q->phead == NULL) //链表为空
	{
		q->phead = node;
		q->ptail = node;
	}
	else //链表不为空
	{
		q->ptail->next = node;
		q->ptail = node;
	}

	q->size++;
}

//出队
void QueuePop(Queue* q)
{
	assert(q);
	assert(q->size > 0);

	if (q->phead->next == NULL) //只有一个结点
		q->ptail = NULL;

	QNode* cur = q->phead;
	q->phead = cur->next;
	free(cur);
	cur = NULL;
	q->size--;
}

//获取队头元素
QDataType QueueFront(Queue* q)
{
	assert(q);
	assert(q->size > 0);

	return q->phead->val;
}

//获取队尾元素
QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(q->size > 0);

	return q->ptail->val;
}

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

	return q->size;
}

//判空
bool QueueEmpty(Queue* q)
{
	assert(q);

	return q->size == 0;
}

//销毁队列
void QueueDestroy(Queue* q)
{
	assert(q);

	QNode* cur = q->phead;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}

	q->phead = NULL;
	q->ptail = NULL;
	q->size = 0;
}


网站公告

今日签到

点亮在社区的每一天
去签到