大家好,我是苏貝,本篇博客带大家了解队列,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️
目录
- 一. 队列的概念及结构
- 二. 队列的实现
- 队列的结构体
- 初始化
- 销毁
- 队尾插入
- 队头删除
- 显示第一个节点的值
- 显示最后一个节点的值
- 是否为空
- 队列的大小
- 三. 模块化代码实现
- Queue.h
- Queue.c
- Test.c
- 结果演示
一. 队列的概念及结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的性质。FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
二. 队列的实现
1
队列的结构体
因为数组在头删的时候不方便,所以我们采用单链表来实现。
typedef int QDataType;
typedef struct QueueNode
{
struct Queue* next;
QDataType val;
}QNode;
typedef struct Queue
{
QNode* phead;
QNode* ptail;
int size;
}Queue;
2
初始化
因为我们要对队列进行初始化,所以实参要传Queue类型变量的地址,用一级指针来接收。因为实参(Queue类型变量的地址)不可能为NULL,所以对它断言(下面的接口同理)。
void QueueInit(Queue* pq)
{
assert(pq);
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
3
销毁
void QueueDestroy(Queue* pq)
{
assert(pq);
while (pq->phead)
{
QNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
pq->ptail = NULL;
pq->size = 0;
}
4
队尾插入
插入前要创建一个新节点,插入时还要判断队列是否为空,若为空则让pq->phead = pq->ptail = newnode。若不为空则只让pq->ptail ->next= newnode,再pq->ptail=pq->ptail->next
注意不要忘记pq->size++
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
//创建一个新节点
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->val = x;
newnode->next = NULL;
//插入
if (pq->phead == NULL)
{
pq->ptail = pq->phead = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}
5
队头删除
删除时要保证队列里有元素,所以对pq->phead断言,下面的显示第一个/最后一个节点的值同理
注意:当队列里只有一个元素时,删除后pq->phead指向NULL没错,但是此时pq->ptail是野指针,所以也要将pq->ptail置为NULL。不要忘记pq->size- -
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->phead);
Queue* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
if (pq->phead == NULL)
{
pq->ptail = NULL;
}
pq->size--;
}
6
显示第一个节点的值
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->phead->val;
}
7
显示最后一个节点的值
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->ptail->val;
}
8
是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->phead == NULL;
}
9
队列的大小
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
三. 模块化代码实现
Queue.h
#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
typedef int QDataType;
typedef struct QueueNode
{
struct Queue* next;
QDataType val;
}QNode;
typedef struct Queue
{
QNode* phead;
QNode* ptail;
int size;
}Queue;
//初始化
void QueueInit(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);
//队尾插入
void QueuePush(Queue* pq, QDataType x);
//队头删除
void QueuePop(Queue* pq);
//显示第一个节点的值
QDataType QueueFront(Queue* pq);
//显示最后一个节点的值
QDataType QueueBack(Queue* pq);
//是否为空
bool QueueEmpty(Queue* pq);
//队列的大小
int QueueSize(Queue* pq);
Queue.c
#include"Queue.h"
//初始化
void QueueInit(Queue* pq)
{
assert(pq);
pq->phead = NULL;
pq->ptail = NULL;
pq->size = 0;
}
//销毁
void QueueDestroy(Queue* pq)
{
assert(pq);
while (pq->phead)
{
QNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
pq->ptail = NULL;
pq->size = 0;
}
//队尾插入
void QueuePush(Queue* pq, QDataType x)
{
assert(pq);
//创建一个新节点
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->val = x;
newnode->next = NULL;
//插入
if (pq->phead == NULL)
{
pq->ptail = pq->phead = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = newnode;
}
pq->size++;
}
//队头删除
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->phead);
Queue* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
if (pq->phead == NULL)
{
pq->ptail = NULL;
}
pq->size--;
}
//显示第一个节点的值
QDataType QueueFront(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->phead->val;
}
//显示最后一个节点的值
QDataType QueueBack(Queue* pq)
{
assert(pq);
assert(pq->phead);
return pq->ptail->val;
}
//是否为空
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->phead == NULL;
}
//队列的大小
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
Test.c
#include"Queue.h"
int main()
{
Queue p;
QueueInit(&p);
QueuePush(&p, 1);
QueuePush(&p, 2);
QueuePush(&p, 3);
QueuePush(&p, 4);
QueuePush(&p, 5);
while (!QueueEmpty(&p))
{
printf("%d ", QueueFront(&p));
QueuePop(&p);
}
QueueDestroy(&p);
return 0;
}
结果演示
好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️