1. 队列的概念及结构
队列的概念:
与栈相比,队列也是一种特殊的线性表,不同的是,队列只允许在一端进行插入数据操作,在另一端进行删除数据操作。队列遵守先进先出 FIFO(First In First Out)的原则。
入队列:进行插入操作的一端称为队尾。
出队列:进行删除操作的一端称为队头。
图解:
2. 队列的实现
1. 队列节点
链表和数组都能实现队列,但相比之下,链表更优,因为数组出队列时在数组头上出数据,效率会比较低。
//队列节点
typedef int QDataType;
//链表和数组都能实现队列,但相比之下
//链表更优,因为数组出队列时在数组头上出数据,效率会比较低。
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QNode;
2. "Que"结构体
增加一个尾指针方便找尾,头指针和尾指针定义为结构体方便传参。
//增加一个尾指针方便找尾,头指针和尾指针定义为结构体方便传参
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Que;
3. 初始化
//初始化
void QueueInit(Que* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
4. 销毁
//销毁
void QueueDestroy(Que* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
5. 入队列
//入队列
void QueuePush(Que* 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->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
6. 出队列
//出队列
void QueuePop(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));//队列为空不能删除
if (pq->head->next == NULL)//剩一个节点时,要避免尾指针成为野指针
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
pq->size--;
}
7. 取队头数据
//取队头数据
QDataType QueueFront(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
8. 取队尾数据
QDataType QueueBack(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
9.判空
bool QueueEmpty(Que* pq)
{
assert(pq);
return pq->head == NULL;
}
10. 求队列大小
//求队列大小
int QueueSize(Que* pq)
{
assert(pq);
return pq->size;
}
3. 测试
int main()
{
Que q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
QueuePush(&q, 5);
while (!QueueEmpty(&q))
{
printf("%d ", QueueFront(&q));
QueuePop(&q);
}
printf("\n");
QueueDestroy(&q);
return 0;
}
源代码
Queue.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
//队列节点
typedef int QDataType;
//链表和数组都能实现队列,但相比之下
//链表更优,因为数组出队列时在数组头上出数据,效率会比较低。
typedef struct QueueNode
{
struct QueueNode* next;
QDataType data;
}QNode;
//增加一个尾指针方便找尾,头指针和尾指针定义为结构体方便传参
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Que;
//初始化
void QueueInit(Que* pq);
//销毁
void QueueDestroy(Que* pq);
//入队列
void QueuePush(Que* pq, QDataType x);
//出队列
void QueuePop(Que* pq);
//取队头数据
QDataType QueueFront(Que* pq);
//取队尾数据
QDataType QueueBack(Que* pq);
//判空
bool QueueEmpty(Que* pq);
//求队列大小
int QueueSize(Que* pq);
Queue.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"
//初始化
void QueueInit(Que* pq)
{
assert(pq);
pq->head = pq->tail = NULL;
pq->size = 0;
}
//销毁
void QueueDestroy(Que* pq)
{
assert(pq);
QNode* cur = pq->head;
while (cur)
{
QNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
pq->size = 0;
}
//入队列
void QueuePush(Que* 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->tail == NULL)
{
pq->head = pq->tail = newnode;
}
else
{
pq->tail->next = newnode;
pq->tail = newnode;
}
}
//出队列
void QueuePop(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));//队列为空不能删除
if (pq->head->next == NULL)//剩一个节点时,要避免尾指针成为野指针
{
free(pq->head);
pq->head = pq->tail = NULL;
}
else
{
QNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
pq->size--;
}
//取队头数据
QDataType QueueFront(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
//取队尾数据
QDataType QueueBack(Que* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
//判空
bool QueueEmpty(Que* pq)
{
assert(pq);
return pq->head == NULL;
}
//求队列大小
int QueueSize(Que* pq)
{
assert(pq);
return pq->size;
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Queue.h"
int main()
{
Que q;
QueueInit(&q);
QueuePush(&q, 1);
QueuePush(&q, 2);
QueuePush(&q, 3);
QueuePush(&q, 4);
QueuePush(&q, 5);
while (!QueueEmpty(&q))
{
printf("%d ", QueueFront(&q));
QueuePop(&q);
}
printf("\n");
QueueDestroy(&q);
return 0;
}