一、概念:
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有
先进先出
FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为
队头
二、队列的实现:
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
三、具体代码实现:
(1)队列的表示方法与结构
队列中每个节点的基本结构为:
在之后我们进行队列的增、删等操作时,往往需要提供两个二级指针,即:
QNode**phead和QNode**ptail,这太麻烦了,为了简化操作,我们继续封装一个结构体,
这样子在传参时我们只需要传Queue*pq一个参数,大大简化了代码。
(2)队列的初始化
(3)队尾入队列
和单链表的插入方式基本一样
(4)队头出队列
在出队列的时候,我们只要让pq->phead向后走,同时释放掉前一个节点就可以了,但需要注意的是,当phead和ptail指向同一个节点时,只释放掉phead会让ptail变成野指针
(5)获取头部元素
(6)获取尾部元素
(7)获取队列中有效元素个数
(8)判断队列是否为空
(9)销毁队列
四、完整代码
Queue.h
#pragma once
#include<stdio.h>
#include<stdbool.h>
#include<assert.h>
#include<stdlib.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 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)
{
q->phead = NULL;
q->ptail = NULL;
q->size = 0;
}
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
assert(q);
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail");
return;
}
newnode->val = data;
newnode->next = NULL;
if (q->ptail == NULL)
{
q->phead = q->ptail = newnode;
}
else
{
q->ptail->next = newnode;
q->ptail = newnode;
}
q->size++;
}
// 队头出队列
void QueuePop(Queue* q)
{
assert(q);
assert(q->size);
if (q->phead->next == NULL)
{
free(q->phead);
q->phead = q->ptail = NULL;
}
else
{
QNode* next = q->phead->next;
free(q->phead);
q->phead = next;
}
q->size--;
}
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
assert(q);
assert(q->size);
return q->phead->val;
}
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
assert(q);
assert(q->size);
return q->ptail->val;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
assert(q);
assert(q->size);
return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
assert(q);
return q->size == 0;
}
// 销毁队列
void QueueDestroy(Queue* q)
{
QNode* cur = q->phead;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = NULL;
cur = next;
}
q->size = 0;
}