目录
一. 队列的定义
二.队列的结构定义
单个元素的结构定义
队列的结构定义
三.队列的接口实现
1.初始化
2.销毁
3.入队列(队尾插入)
4.出队列(队头删除)
5.获取队首元素
6.获取队尾元素
7.获取队列元素个数
8.队列判空
四.C语言实现代码
Queue.h
Queue.c
💓 博客主页:C-SDN花园GGbond
⏩ 文章专栏:探索数据结构与算法
一. 队列的定义
队列(queue)是一种只允许在一端进行插入操作,而在另一端进行删除操作的线性表。其严格遵循先进先出(First In First Out)的规则,简称FIFO。
基本概念:
先进先出(FIFO)原则:这是队列的核心特性。它意味着最早被添加到队列中的元素将是第一个被移除的元素。这个原则确保了数据处理的顺序性。
队头(Front):队列中第一个被添加的元素位于队头,但它不是永远位于队列的第一个位置,而是指按照入队顺序,最先应该被出队的元素的位置。在出队操作中,总是从队头移除元素。
队尾(Rear)或队末:新元素总是被添加到队列的这一端。在入队操作中,新元素总是被放置在队尾。
队列为空:当队列中没有元素时,称队列为空队列。
队列满:在某些实现中,特别是使用静态数组实现的队列,当队列无法再添加新元素时,称为队列满。但在使用链表实现的队列中,通常不会遇到队列满的情况,因为链表可以动态扩展。
二.队列的结构定义
单个元素的结构定义
- 数据部分
- 指向下一个元素的指针next
// 链式结构:表示队列
typedef int QDataType;
typedef struct QListNode
{
struct QListNode* next;
QDataType data;
}QNode;
队列的结构定义
- 指向队首元素的指针phead
- 指向队尾元素的指针ptail
- 队列的元素个数size
// 队列的结构
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
将队列的首尾指针封装成一个结构体,可以方便函数调用,统一接口
另外使用一个整型变量记录元素个数,利于其他函数功能实现
三.队列的接口实现
1.初始化
- 对形参判空(接收的地址必须是有效的(队列必须存在)
- 队列的首尾指针初始化为NULL
- size变量初始化为0
// 初始化队列
void QueueInit(Queue* q)
{
assert(q);//接收的地址必须是有效的(队列必须存在)
q->head = q->tail = NULL;
q->size = 0;
}
2.销毁
- 对形参判空
- 创建指针循环遍历链表: 每次记录下指针的下一个节点,释放指针指向的节点,指针指向下一个节点
- 出循环后,将首尾指针指向NULL
- size置0
// 销毁队列
void QueueDestroy(Queue* q)
{
assert(q);
while (q->head)//释放所有节点
{
QNode* next = q->head->next;
free(q->head);
q->head = next;
}
q->head = q->tail = NULL;
q->size = 0;
}
3.入队列(队尾插入)
接收两个参数,队列的地址和要插入的数据
首先,对形参指针判空
然后申请新节点,next指针指向NULL,数据部分为要插入的数据
接下来,对空队列和非空队列分别处理:
空队列直接让首尾指针都指向新节点
非空队列:尾指针指向节点的next指针指向新节点,尾指针再指向新节点
完成插入之后,size++
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
assert(q);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)//判定是否申请成功
{
perror("newnode error\n");
exit(1);
}
newnode->data = data;
newnode->next = NULL;
if (q->head == NULL)//对空队列入队的处理
{
q->head = q->tail = newnode;
}
else //对非空队列入队的处理
{
q->tail->next = newnode;
q->tail = newnode;
}
q->size++;
}
4.出队列(队头删除)
- 对形参判空
- 对队列判空
- 队首删除分两种情况
- 队列只有一个元素的情况: 释放该元素空间,首尾指针都指向NULL
- 队列有多个元素的情况: 记录下第二个节点地址,释放首节点,首指针指向第二个节点
- 删除完节点之后,size--
// 队头出队列
void QueuePop(Queue* q)
{
assert(q);
assert(q->head);//队列不能为空
if (q->head == q->tail)//对只有一个元素的队列的出队处理
{
free(q->head);
q->head = q->tail = NULL;
}
else //对存在多个元素的队列的出队处理
{
QNode* next = q->head->next;
free(q->head);
q->head = next;
}
q->size--;
}
5.获取队首元素
- 形参判空
- 队列判空
- 返回队首元素的数据
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
assert(q);
assert(q->head);//队列不能为空
return q->head->data;
}
6.获取队尾元素
- 形参判空
- 队列判空
- 返回队尾元素的数据
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
assert(q);
assert(q->head);
return q->tail->data;
}
7.获取队列元素个数
- 形参判空
- 返回size
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
assert(q);
return q->size;
}
8.队列判空
- 形参判空
- 返回size==0的结果
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
assert(q);
return q->size == 0;
}
四.C语言实现代码
Queue.h
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
// 链式结构:表示队列
typedef int QDataType;
typedef struct QListNode
{
struct QListNode* next;
QDataType data;
}QNode;
// 队列的结构
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
// 初始化队列
void QueueInit(Queue* q);
// 队尾入队列
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);
Queue.c
#include"Queue.h"
// 初始化队列
void QueueInit(Queue* q)
{
assert(q);//接收的地址必须是有效的(队列必须存在)
q->head = q->tail = NULL;
q->size = 0;
}
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
assert(q);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)//判定是否申请成功
{
perror("newnode error\n");
exit(1);
}
newnode->data = data;
newnode->next = NULL;
if (q->head == NULL)//对空队列入队的处理
{
q->head = q->tail = newnode;
}
else //对非空队列入队的处理
{
q->tail->next = newnode;
q->tail = newnode;
}
q->size++;
}
// 队头出队列
void QueuePop(Queue* q)
{
assert(q);
assert(q->head);//队列不能为空
if (q->head == q->tail)//对只有一个元素的队列的出队处理
{
free(q->head);
q->head = q->tail = NULL;
}
else //对存在多个元素的队列的出队处理
{
QNode* next = q->head->next;
free(q->head);
q->head = next;
}
q->size--;
}
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
assert(q);
assert(q->head);//队列不能为空
return q->head->data;
}
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
assert(q);
assert(q->head);
return q->tail->data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
assert(q);
return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
assert(q);
return q->size == 0;
}
// 销毁队列
void QueueDestroy(Queue* q)
{
assert(q);
while (q->head)//释放所有节点
{
QNode* next = q->head->next;
free(q->head);
q->head = next;
}
q->head = q->tail = NULL;
q->size = 0;
}