目录
1. 队列
2.1 队列的概念及结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头。
2.2 队列的实现
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
2.队列的基本功能实现
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
typedef int QEDateType;
typedef struct QListNode
{
struct QListNode* _next; //链表所指向的下一个节点
QEDateType _data; //节点所储存的数据
}QLNode;
typedef struct Queue
{
int _size; //队列大小
QLNode* _front; //队列头
QLNode* _rear; //队列尾
}QE;
//队列初始化
void QueueInit(QE* qq);
//队列的入列(尾)
void QueuePush(QE* qq, QEDateType n);
//队列的出列(头)
void QueuePop(QE* qq);
//队列头
QEDateType QueueRear(QE* qq);
//队列尾
QEDateType QueueFront(QE* qq);
//队列的销毁
void QueueDestory(QE* qq);
//队列的大小
int QueueSize(QE* qq);
//判断队列是否为空
//为空返回1,不为空返回0
bool QueueEmpty(QE* qq);
2.1 结构体的创建
利用结构体的特点,对这些信息进行整体管理操作。
typedef int QEDateType;
typedef struct QListNode
{
struct QListNode* _next; //链表所指向的下一个节点
QEDateType _data; //节点所储存的数据
}QLNode;
typedef struct Queue
{
int _size; //队列大小
QLNode* _front; //队列头
QLNode* _rear; //队列尾
}QE;
2.2 队列初始化
//队列初始化
void QueueInit(QE* qq)
{
assert(qq); //防止传入地址为NULL,造成野指针的问题
//初始化
qq->_size = 0;
qq->_front = qq->_rear = NULL;
}
2.3 判断队列是否为空(为空返回1,不为空返回0)
//判断队列是否为空
//为空返回1,不为空返回0
bool QueueEmpty(QE* qq)
{
assert(qq);
//第一个节点为空,队列为空
return qq->_front == NULL;
}
2.4 队列的入列(尾)
//队列的入列(尾)
void QueuePush(QE* qq, QEDateType n)
{
assert(qq);
//创建一个新节点
QLNode* newnode = (QLNode*)malloc(sizeof(QLNode));
//防止malloc创建失败
if (newnode == NULL)
{
printf("malloc fail\n");
exit(-1);
}
//创建成功初始化新节点
newnode->_next = NULL;
newnode->_data = n;
//防止没有第一个节点,不然没法连接
if (qq->_front == NULL)
{
//队列第一个元素
qq->_front = qq->_rear = newnode;
}
else
{
//根据物理结构,连接数据
qq->_rear->_next = newnode;
qq->_rear = newnode;
}
//数据个数加一
qq->_size++;
}
2.5 队列的出列(头)
//队列的出列(头)
void QueuePop(QE* qq)
{
assert(qq);
//单独纯属,便于后期free
QLNode* del = qq->_front;
qq->_front = qq->_front->_next;
free(del);
//数据个数减一
qq->_size--;
}
2.6 队列头
//队列头
QEDateType QueueRear(QE* qq)
{
assert(qq);
//直接返回物理结构的第一个节点的数据(返回逻辑结构的第一个数据)
return qq->_front->_data;
}
2.7 队列尾
//队列尾
QEDateType QueueFront(QE* qq)
{
assert(qq);
//直接返回物理结构的最后一个节点的数据(返回逻辑结构的最后一个数据)
return qq->_rear->_data;
}
2.8 队列的大小
//队列的大小
int QueueSize(QE* qq)
{
assert(qq);
return qq->_size;
}
2.9 队列的销毁
因为对于队列的开辟使用的是动态内存,所以销毁是必须的。
//队列的销毁
void QueueDestory(QE* qq)
{
assert(qq);
//当根据物理结构qq->_front为NULL时,数据已全部遍历
while (qq->_front != NULL)
{
//单独纯属,便于后期free
QLNode* del = qq->_front;
qq->_front = qq->_front->_next;
free(del);
}
//因为,已经全部free掉,防止野指针的问题,所以都初始化为NULL
qq->_front = qq->_rear = NULL;
}