目录
一、概念与结构
只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,遵循先进先出的结构。
入队列:进行插入操作的一端叫作队尾
出队列:进行删除操作的一端叫做队头
队列的实现可以通过数组和链表来实现。
二、队列的实现
本文章通过单链表实现队列,单链表详情见C学习(数据结构)->单链表-CSDN博客
1、队列的结构
单链表的第一个结点当做队头,最后一个节点当做队尾,且单链表结点的结构
typedef int QDataType;
typedef struct QueueNode
{
QDataType data;
struct QueueNode* next;
}QNode;
由于单链表结构的特殊性,导致进行入队操作的时候,得先遍历一遍单链表,才能在队尾进行结点的插入,时间负复杂度为 O( n ) ,所以要建立一个新的结构体来保存单链表的第一个结点和最后一个结点,把时间复杂度降为 O(1) ,则优化后的队列结构
//定义队列结构
typedef int QDataType;
typedef struct QueueNode
{
QDataType data;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* phead;//队头
QNode* ptail;//队尾
int size;//队列有效元素个数
}Qu;
2、队列的初始化
//队列的初始化
void QueueInit(Qu* pq)
{
assert(pq);
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
3、判断队列是否为空
//判断队列是否为空
bool QueueEmpty(Qu* pq)
{
assert(pq);
return pq->phead == NULL && pq->ptail == NULL;
}
4、入队列和出队列
入队列
//入队列
void QueuePush(Qu* pq, QDataType x)
{
assert(pq);
//申请新结点
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail!!!");
exit(1);
}
//赋值
newnode->data = x;
newnode->next = NULL;
//入队列
if (pq->phead == NULL)//如果队列为空
{
pq->phead = pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = pq->ptail->next;
}
//有效数据加一
pq->size++;
}
出队列
//出队列
void QueuePop(Qu* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
//如果只有一个节点,避免phead,ptail变为野指针
if (pq->phead == pq->ptail)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else
{
//删除队头
QNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
//有效数据减一
--pq->size;
}
5、取队头、队尾数据
取队头数据
//取队头数据
QDataType QueueFront(Qu* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->phead->data;
}
取队尾数据
//取队尾数据
QDataType QueueBack(Qu* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->ptail->data;
}
6、队列有效数据个数
//队列有效元素个数
int QueueSize(Qu* pq)
{
assert(pq);
return pq->size;
}
7、队列的销毁
//销毁队列
void QueueDestroy(Qu* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
QNode* pcur = pq->phead;
//循环出栈销毁
while (pcur)
{
QNode* next = pcur->next;
free(pcur);
pcur = next;
}
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
三、总代码
头文件 Queue.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
//定义队列结构
typedef int QDataType;
typedef struct QueueNode
{
QDataType data;
struct QueueNode* next;
}QNode;
typedef struct Queue
{
QNode* phead;//队头
QNode* ptail;//队尾
int size;//队列有效元素个数
}Qu;
//队列的初始化
void QueueInit(Qu* pq);
//入队列
void QueuePush(Qu* pq, QDataType x);
//判断队列是否为空
bool QueueEmpty(Qu* pq);
//出队列
void QueuePop(Qu* pq);
//取队头数据
QDataType QueueFront(Qu* pq);
//取队尾数据
QDataType QueueBack(Qu* pq);
//队列有效元素个数
int QueueSize(Qu* pq);
//销毁队列
void QueueDestroy(Qu* pq);
函数 Queue.cpp
#include"Queue.h"
//队列的初始化
void QueueInit(Qu* pq)
{
assert(pq);
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
//入队列
void QueuePush(Qu* pq, QDataType x)
{
assert(pq);
//申请新结点
QNode* newnode = (QNode*)malloc(sizeof(QNode));
if (newnode == NULL)
{
perror("malloc fail!!!");
exit(1);
}
//赋值
newnode->data = x;
newnode->next = NULL;
//入队列
if (pq->phead == NULL)//如果队列为空
{
pq->phead = pq->ptail = newnode;
}
else
{
pq->ptail->next = newnode;
pq->ptail = pq->ptail->next;
}
pq->size++;
}
//判断队列是否为空
bool QueueEmpty(Qu* pq)
{
assert(pq);
return pq->phead == NULL && pq->ptail == NULL;
}
//出队列
void QueuePop(Qu* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
//如果只有一个节点,避免phead,ptail变为野指针
if (pq->phead == pq->ptail)
{
free(pq->phead);
pq->phead = pq->ptail = NULL;
}
else
{
//删除队头
QNode* next = pq->phead->next;
free(pq->phead);
pq->phead = next;
}
--pq->size;
}
//取队头数据
QDataType QueueFront(Qu* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->phead->data;
}
//取队尾数据
QDataType QueueBack(Qu* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->ptail->data;
}
//队列有效元素个数
int QueueSize(Qu* pq)
{
assert(pq);
return pq->size;
}
//销毁队列
void QueueDestroy(Qu* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
QNode* pcur = pq->phead;
//循环出栈销毁
while (pcur)
{
QNode* next = pcur->next;
free(pcur);
pcur = next;
}
pq->phead = pq->ptail = NULL;
pq->size = 0;
}
测试 main.cpp
#include"Queue.h"
void QueueTest01()
{
Qu q;
//初始化
QueueInit(&q);
//入队列
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
QueuePush(&q, 5);
//有效元素个数
printf("%d\n", QueueSize(&q));
//取队头元素,取队尾元素
QDataType x = QueueFront(&q);
printf("%d\n", x);
x = QueueBack(&q);
printf("%d\n", x);
//出队列
x = QueueFront(&q);
printf("%d\n", x);
QueuePop(&q);
//有效元素个数
printf("%d\n", QueueSize(&q));
//销毁队列
QueueDestroy(&q);
}
int main()
{
QueueTest01();
return 0;
}