目录
队列的定义
队列的实现分析
代码实现
Queue.h
Queue.c
队列的定义
队列是只允许在一端进行插入操作,而在另一段进行删除操作的线性表。
首先,让我们来看一看生活中的队列,当我们去银行办理业务的时候,我们进入银行的时候,都会去取票机那里去一个专属我们的序号,当客服通过语音播报的时候,如果是我们手里拿的好嘛时,就轮到我们办理业务了。这是一种非常公平的方法,先来的人先办理业务,后来的人就只能等到前面的人办理完业务之后才到你。这种方法是非常公平的。
我们再来看一个例子,当我们在玩电脑的时候,当电脑不知道是什么原因卡死的时候。我们可能会疯狂的点击左键,想要把我们进行的操作点出来,可是电脑却没有反应。可是过了一会,电脑突然不卡了,你就会发现出现了很多很多同样的应用或者网页,这就是当我们点击鼠标时,鼠标已经把信息传给了电脑,每一个操作都在排队等待被进行,所以说会出现很多相同的应用或者网页。
我们可以看到,队列就像是一个单向通道,只能向前走,不能后退。
队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端叫做队尾,允许删除的一端叫做队头。
队列的实现分析
队列也有着两种实现方式,一种是链式结构,一种是顺序结构。相比于栈实现我们用的顺序结构,在队列中我们用链式结构来实现要好一点。
队列使用顺序表实现的弊端:当我们从队头出数据的时候,需要改变队头的指向,随着删除的数据增多,就会出现多余的空间浪费,这是我们就需要定义一个循环队列了,而循环队列的大小是固定的,操作起来又会很不方便,所以说我们选择使用链式结构来实现队列。
队列的链式储存结构,其实就是线性表的单链表,只不过它只能尾进头出而已,我们把它简称为链队列。因为队列只在头和尾进行操作,所以说我们只需要定义两个指针,一个指向头,一个指向尾就行了。队列的插入与删除也很方便,我们只需要将删除的节点释放掉,改变头指针的指向就行,插入的时候我们只需要改变尾指针的指向就可以了。
分析了这么多,下面就让我们来实现一下代码吧。
代码实现
Queue.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
//函数声明 结构体声明
//定义数据类型
typedef int datatype;
//定义节点
typedef struct QNode
{
datatype data;
struct QNode* next;
}QNode;
typedef struct Queue
{
//头节点
QNode* head;
//尾节点
QNode* tail;
}Queue;
//队列初始化
void InitQueue(Queue* sp);
//队列插入 (头删尾插)
void InsertQueue(Queue* tmp);
//出队列
void PopQueue(Queue* tmp);
//销毁队列
void DestroyQueue(Queue* tmp);
//队头数据
datatype FrontQueue(Queue* tmp);
//队尾数据
datatype BackQueue(Queue* tmp);
//队列长度
int QueueSize(Queue* tmp);
//队列是否为空
bool QueueEmpty(Queue* tmp);
Queue.c
#include "Queue.h"
//函数实现
//队列初始化
void InitQueue(Queue* sp)
{
assert(sp);
sp->head = NULL;
sp->tail = NULL;
}
//链表插入 (头删尾插)
void InsertQueue(Queue* tmp,datatype x)
{
assert(tmp);
QNode* cur = (QNode*)malloc(sizeof(QNode));
if (cur == NULL)
{
perror("malloc fail");
exit(-1);
}
cur->data = x;
cur->next = NULL;
//如果是空队列,先直接赋值
if (tmp->tail ==NULL)
{
tmp->head = cur;
tmp->tail = cur;
}
//如果不是空队列,就尾插
else
{
tmp->tail->next = cur;
tmp->tail = cur;
}
}
//出队列
void PopQueue(Queue* tmp)
{
assert(tmp);
//队列的头不能为空
assert(tmp->head);
//只有一个节点的情况
if (tmp->head->next==NULL)
{
free(tmp->head);
tmp->head =tmp->tail= NULL;
}
//不只有一个节点的情况
else
{
QNode* cur = tmp->head->next;
free(tmp->head);
tmp->head = cur;
}
}
//队头数据
datatype FrontQueue(Queue* tmp)
{
assert(tmp);
assert(tmp->head);
return tmp->head->data;
}
//队尾数据
datatype BackQueue(Queue* tmp)
{
assert(tmp);
assert(tmp->tail);
return tmp->tail->data;
}
//队列长度
int QueueSize(Queue* tmp)
{
int count = 0;
QNode* cur = tmp->head;
//遍历队列
while (cur)
{
count++;
cur = cur->next;
}
//返回长度
return count;
}
//队列是否为空
bool QueueEmpty(Queue* tmp)
{
//是空返回true 不是空返回false
return tmp->head == NULL;
}
//销毁队列
void DestroyQueue(Queue* tmp)
{
assert(tmp);
QNode* del = tmp->head;
//释放节点
while (del)
{
QNode* cur = del->next;
free(del);
del = cur;
}
del = NULL;
tmp->head = tmp->tail = NULL;
}
以上就是关于队列的实现以及我对队列的一些理解,如果有什么错误还请大家指出。