目录
队列的定义
队列的实现分析
代码实现
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 不是空返回falsereturn 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;
}
以上就是关于队列的实现以及我对队列的一些理解,如果有什么错误还请大家指出。