【数据结构】千字深入浅出讲解队列(附原码 | 超详解)
🚀write in front🚀
📝个人主页:认真写博客的夏目浅石.
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏:C语言实现数据结构
💬总结:希望你看完之后,能对你有所帮助,不足请指正!共同学习交流 🖊
✉️如果无聊的话,就来逛逛我的博客栈吧stack-frame.cn
文章目录
- 前言
- 一、队列的概念
- 二、队列的结构
- 三、队列的实现
- 3.1结构体的定义
- 3.2函数接口
- 3.3初始化
- 3.4销毁
- 3.5入队列
- 3.6出队列
- 3.7计算队列大小
- 3.8判断队列是否为空
- 3.9取对头元素
- 3.10取队尾元素
- 四、队列的总代码
- 总结
前言
今天打算给大家讲解队列这一个知识点,会把函数接口一一列举出来 并且 依次实现,这样才会更加牢固的掌握队列这一基本数据结构,话不多说,让我们一起来学习吧。
一、队列的概念
队列 与 栈 链表都是一种线性表结构。
队列:
只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头
数据结构图如下:
二、队列的结构
队列可以使用 数组 或 链表实现,但是二者之间有不同的地方,哪一个更加适合队列呢?
我想:使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数
组头上出数据,效率会比较低。
三、队列的实现
3.1结构体的定义
typedef char QDatatype;
typedef struct QueueNode
{
struct QueueNode* next;
QDatatype data;
}QNode;
由于链表的尾插比较麻烦,而队列的入数据为尾插。所以定义队列的结构体时,可以定义两个指针
head
和tail
分别对应 队头 和 队尾 ,tail
的引入就是方便尾插再在给定一个size
实时记录队列的大小。
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
3.2函数接口
void QueueInit(Queue* pq);//初始化
void QueueDestroy(Queue* pq);//销毁
void QueuePush(Queue* pq,QDatatype x);//入队列
void QueuePop(Queue* pq);//出队列
int QueueSize(Queue* pq);//计算队列大小
bool QueueEmpty(Queue* pq);//判断队列是否为空
QDatatype QueueFront(Queue* pq);//取对头元素
QDatatype QueueBack(Queue* pq);//取队尾元素
3.3初始化
要领: 队列对头队尾相等都为NULL,且size=0;
void QueueInit(Queue* pq)
{
//暴力检查
assert(pq);
pq->head=pq->tail=NULL;
pq->size=0;
}
3.4销毁
要领: 取cur
不断遍历,然后free
节点,最后处理head
与tail
即可;
void QueueDestroy(Queue* pq)
{
assert(pq);
Queue* cur=pq->head;
while(cur)
{
Queue* tmp=cur->next;
free(cur);
cur=tmp;
}
pq->head=pq->tail=NULL;
pq->size=0;
}
3.5入队列
要领: 尾节点(tail)进行插入;
void QueuePush(Queue* pq,QDatatype x)
{
Queue* newnode=(Queue*)malloc(sizeof(Queue));
if(newnode==NULL)
{
perror("malloc fail");
return;
}
newnode->data=x;
newnode->nxet=NULL;
if(pq->head=NULL)
{
assert(pq->tail==NULL)
pq->head=pq->tail=newnode;
}
else
{
pq->tail->next=newnode;
pq->tail=newnode;
}
pq->size++;
}
3.6出队列
要领: 找到原本头节点的下一个节点 更换一下新的头节点就好了,注意free就行
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->head!=NULL);
Queue* tmp=pq->head->next;
free(pq->head);
pq->head=tmp;
if(pq->head==NULL)
{
pq->tail=NULL;
}
pq->size--;
}
3.7计算队列大小
要领: 返回size的大小即可;
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
3.8判断队列是否为空
要领: 其实本质就是看size是否为0;
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->size==0;
}
3.9取对头元素
要领: 队列非空,取 head 出数据
QDatatype QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
3.10取队尾元素
要领: 队列非空,取 tail 处数据。
QDatatype QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
四、队列的总代码
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef char QDatatype;
typedef struct QueueNode
{
struct QueueNode* next;
QDatatype data;
}QNode;
typedef struct Queue
{
QNode* head;
QNode* tail;
int size;
}Queue;
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);
void QueuePush(Queue* pq,QDatatype x);
void QueuePop(Queue* pq);
int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);
QDatatype QueueFront(Queue* pq);
QDatatype QueueBack(Queue* pq);
//--------------------------手动分割线---------------------------
//初始化
void QueueInit(Queue* pq)
{
//暴力检查
assert(pq);
pq->head=pq->tail=NULL;
pq->size=0;
}
//--------------------------手动分割线---------------------------
//销毁
void QueueDestroy(Queue* pq)
{
assert(pq);
Queue* cur=pq->head;
while(cur)
{
Queue* tmp=cur->next;
free(cur);
cur=tmp;
}
pq->head=pq->tail=NULL;
pq->size=0;
}
//--------------------------手动分割线---------------------------
void QueuePush(Queue* pq,QDatatype x)
{
Queue* newnode=(Queue*)malloc(sizeof(Queue));
if(newnode==NULL)
{
perror("malloc fail");
return;
}
newnode->data=x;
newnode->nxet=NULL;
if(pq->head=NULL)
{
assert(pq->tail==NULL)
pq->head=pq->tail=newnode;
}
else
{
pq->tail->next=newnode;
pq->tail=newnode;
}
pq->size++;
}
//--------------------------手动分割线---------------------------
void QueuePop(Queue* pq)
{
assert(pq);
assert(pq->head!=NULL);
Queue* tmp=pq->head->next;
free(pq->head);
pq->head=tmp;
if(pq->head==NULL)
{
pq->tail=NULL;
}
pq->size--;
}
//--------------------------手动分割线---------------------------
int QueueSize(Queue* pq)
{
assert(pq);
return pq->size;
}
//--------------------------手动分割线---------------------------
bool QueueEmpty(Queue* pq)
{
assert(pq);
return pq->size==0;
}
//--------------------------手动分割线---------------------------
QDatatype QueueFront(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->head->data;
}
//--------------------------手动分割线---------------------------
QDatatype QueueBack(Queue* pq)
{
assert(pq);
assert(!QueueEmpty(pq));
return pq->tail->data;
}
总结
今天学习了单链表的知识,初次写数据结构的知识,给我的感觉就是,学三遍不如手敲代码一遍来的实在,所以数据结构的学习我将多画图,多敲代码来学习
,希望大家吸取经验和我一起学习数据结构,为后面打比赛刷题打下坚实基础。
我是夏目浅石,希望和你一起学习进步,刷题无数!!!希望各位大佬
能一键三连支持一下博主
,hhhh~我们下期见喽
如果无聊的话,就来逛逛我的博客栈吧stack-frame.cn
✨ 原创不易,还希望各位大佬支持一下 \textcolor{blue}{原创不易,还希望各位大佬支持一下} 原创不易,还希望各位大佬支持一下
👍 点赞,你的认可是我创作的动力! \textcolor{9c81c1}{点赞,你的认可是我创作的动力!} 点赞,你的认可是我创作的动力!
⭐️ 收藏,你的青睐是我努力的方向! \textcolor{ed7976}{收藏,你的青睐是我努力的方向!} 收藏,你的青睐是我努力的方向!
✏️ 评论,你的意见是我进步的财富! \textcolor{98c091}{评论,你的意见是我进步的财富!} 评论,你的意见是我进步的财富!