目录
1 队列的概念及结构
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。
队列中元素具有先进先出FIFO(Fast In Fast Out)的特性。
其中,进行插入操作的一端称为队尾,进行入列;进行删除操作的一端称为队头,进行出列。
![](https://i-blog.csdnimg.cn/blog_migrate/0a7fb7fccf829730195541a5671974bd.jpeg)
2 队列的实现
我们使用链表来对队列进行实现,因为使用数组结构的话,出先进数据的效率较低。
2.1 头文件内容
#ifndef _Queue_H
#define _Queue_H
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int QDataType;
//节点结构
typedef struct QListNode
{
struct QListNode* _pNext;
QDataType _data;
}QNode;
//队列结构
typedef struct Queue
{
QNode* _front;//指向队头
QNode* _rear;//指向队尾
}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结果,不为空返回0
int QueueEmpty(Queue* q);
//销毁队列
void QueueDestory(Queue* q);
#endif
2.2 头文件内容实现
- 初始化队列
//初始化队列
void QueueInit(Queue* q)
{
assert(q);
q->_front = NULL;
q->_rear = NULL;
}
- 队尾入队列
//队尾入队列
void QueuePush(Queue* q, QDataType data)
{
assert(q);
//数据的链表尾插
QNode* newNode = (QNode*)malloc(sizeof(QNode));
if (newNode == NULL){
printf("newNode进行malloc开辟失败\n");
return;
}
newNode->_data = data;
newNode->_pNext = NULL;
//1.队列为空,即链表中不存在节点
if (QueueEmpty(q)){
q->_front = newNode;
q->_rear = newNode;
}
//2.队列不空,即链表中存在节点
else{
//进行back之后的尾插即可
q->_rear->_pNext = newNode;
q->_rear = newNode;
}
}
- 队头出队列
//队头出队列
void QueuePop(Queue* q)
{
assert(q);
//1.队列为空,即链表中不存在节点
if (QueueEmpty(q)){
//无头节点可出队列,直接返回即可
printf("队列为空,无头节点可出\n");
return;
}
//2.队列不空,即即链表中存在节点
//2.1链表中仅存在一个节点
else if (q->_front == q->_rear){
//释放头节点,并将链表制空
free(q->_front);
q->_front = NULL;
q->_rear = NULL;
}
//2.2链表中存在≥2个节点
else{
//进行链表的头节点出链表即可
QNode* Fakefornt = q->_front;//先保存队列原头节点
q->_front = Fakefornt->_pNext;//再让头节点后移
free(Fakefornt);//释放旧头节点
}
}
- 获取队列头部元素
//获取队列头部元素
QDataType QueueFront(Queue* q)
{
assert(q);
return q->_front->_data;
}
- 获取队列尾部元素
//获取队列尾部元素
QDataType QueueBack(Queue* q)
{
assert(q);
return q->_rear->_data;
}
- 获取队列中有效元素个数
//获取队列中有效元素个数
int QueueSize(Queue* q)
{
assert(q);
QNode* cur = q->_front;//定义遍历用指向
int count = 0;
while (cur){
count++;
cur = cur->_pNext;
}
return count;
}
- 检测队列是否为空,为空返回非0结果,不为空返回0
//检测队列是否为空,为空返回非0结果,不为空返回0
int QueueEmpty(Queue* q)
{
assert(q);
return NULL == q->_front;//如果头节点对应空,则队列为空,即条件成立,返回1
}
- 销毁队列
//销毁队列
void QueueDestory(Queue* q)
{
assert(q);
QNode* cur = q->_front;
while (cur){
//头删
q->_front = cur->_pNext;
free(cur);
cur = q->_front;
}
//删除节点之后,将空队列结构制空
q->_front = NULL;
q->_rear = NULL;
}
2.3 测试用主函数
//测试用主函数
int main()
{
Queue s;
//初始化队列
QueueInit(&s);
//队尾入队列
QueuePush(&s, 1);
QueuePush(&s, 2);
QueuePush(&s, 3);
QueuePush(&s, 4);
QueuePush(&s, 5);
//打印头尾部元素和队列中元素个数
printf("Front == %d\n", QueueFront(&s));
printf("Back == %d\n", QueueBack(&s));
printf("Size == %d\n", QueueSize(&s));
//队头出队列
QueuePop(&s);
QueuePop(&s);
//打印头尾部元素和队列中元素个数
printf("Front == %d\n", QueueFront(&s));
printf("Back == %d\n", QueueBack(&s));
printf("Size == %d\n", QueueSize(&s));
QueueDestory(&s);
if (QueueEmpty(&s)){
printf("队列销毁成功\n");
}
else{
printf("队列销毁失败\n");
}
return 0;
}