• 初阶数据结构之队列的实现(六)



    😏专栏导读

    👻作者简介:M malloc,致力于成为嵌入式大牛的男人
    👻专栏简介:本文收录于 初阶数据结构,本专栏主要内容讲述了初阶的数据结构,如顺序表,链表,栈,队列等等,专为小白打造的文章专栏。
    👻相关专栏推荐:LeetCode刷题集,C语言每日一题


    🤖文章导读

    本章我将详细的讲解关于栈的知识点
    在这里插入图片描述

    🙀什么是队列?

    队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头

    队列的两种概念:
    1、入队列:进行插入操作的一端称为队尾
    2、出队列:进行删除操作的一端称为队头

    🙀画图描述

    如下图所示,就是入队列出队列全过程啦!关于队列有一个特点就是先进先出不要忘记啦!

    在这里插入图片描述

    关于队列的指示就是,先进先出,队尾进,队头出。

    😳队列的代码实现及其各类讲解

    😳队列实现的理论过程

    队列也可以用数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
    在这里插入图片描述
    在这里插入图片描述

    😳队列的初始化代码实现及其讲解

    😳队列的初始化

    首先我们先定义一个结构体类型(这里我们选择使用的是链式队列):

    typedef int	QDatatype;
    typedef struct QueueNode
    {
    	struct QueueNode* next;
    	QDatatype data;
    }QNode;
    
    typedef struct Queue
    {
    	QNode* phead;
    	QNode* ptail;
    	int size;
    }Queue;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    第一段结构体类型其实是定义这个节点的类型,第二个结构体定义的是这个队列类型。

    队列的初始化
    代码如下:

    void QueueInit(Queue* pq)
    {
    	assert(pq);
    	pq->phead = NULL;
    	pq->ptail = NULL;
    	pq->size = 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    首先assert是断言,当我们这个队列为空的时候,我们程序就会报错,直接结束进程。相对应的初始化,如果指针的话我们赋值为NULL就行啦!

    😳队列的销毁代码实现及其讲解

    因为我们用的是链式队列,而不是数组队列,所以对于每一个节点我们都应该释放掉,因为malloc开辟的是在堆上开辟的。那么具体的是指什么时候呢?

    首先:这是我们最开始的情况

    在这里插入图片描述

    我们要记住,在遍历的过程中永远不要动最初的指针,我们一定要把它赋值给一个指针,让他遍历,我们应该从头开始删除,于是就有了下图,我们把head赋给了cur

    在这里插入图片描述

    如下图所示,此时的next值存储的是cur->next,当我们在遍历的过程中,我们把cur,free掉之后,我们就可以通过next找到下一个我们想要销毁的指针,直到这一片位置全被销毁位置!

    在这里插入图片描述

    void QueueDestroy(Queue* pq)
    {
    	assert(pq);
    	QNode* cur = pq->phead;
    	while (cur)
    	{
    		QNode* next = cur->next;
    		free(cur);
    		cur = next;
    	}
    	pq->phead = pq->ptail = NULL;
    	pq->size = 0;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    😳队列的插入代码实现及其讲解

    在实现代码的时候,我们要先考虑,我们应该怎么插入。此时我们会发现插入其实很像单链表的头插,我们可以理解为这是加入了限制条件的链表,也就是队列。

    在插入的时候我们应该考虑多种情况,例如
    1、此时这是一个空的队列,我们应该如何插入
    2、也就是有节点的队列如何插入。

    好啦知道了我们要做什么了,现在我们就应该开始进行我们的画图描述啦!

    1、首先我们应该先malloc一块新的节点出来,然后让他赋给链表,那我们如何知道这块队列是空的呢?这个时候,就需要来看到tail了,我们可以想象一下,如果尾结点是NULL值,那么是不是代表着此时的队列就是空的呢?是滴!

    所以我们第一步就应该先判断我们的tail指针是否为空,如果为空,我们直接把新节点赋给尾指针就行了。

    那么此时是不是已经有一个节点了呢?如下图所示:

    在这里插入图片描述

    接下来我们要做的操作类似于单链表的尾插操作啦!首先我们要让tail的next指向newnode,然后在把tail指针的位置移动到newnode此时的位置,并且最后再让size++

    在这里插入图片描述

    void QueuePush(Queue* pq, QDatatype x)
    {
    	assert(pq);
    
    	QNode* newnode = (QNode*)malloc(sizeof(QNode));
    	if (newnode == NULL)
    	{
    		perror("malloc fail\n");
    		return;
    	}
    	newnode->data = x;
    	newnode->next = NULL;
    	if (pq->ptail == NULL)
    	{
    		assert(pq->phead == NULL);
    		pq->phead = pq->ptail = newnode;
    	}
    	else
    	{
    		pq->ptail->next = newnode;
    		pq->ptail = newnode;
    	}
    	pq->size++;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    😳队列的删除代码实现及其讲解

    在队列做删除操作时,我们也要知道,我们删除的时候也是从队头进行删除,其实就是头删啦。

    这里我们也得考虑两种情况,例如:
    1、当我们队列只有一个节点的时候,我们应该如何删除呢?
    2、也就是正常情况啦,也就是多个节点的情况

    如果节点只有一个的情况我们需要考虑的是,直接free掉就行啦,
    但是如果有多个节点的时候,我们就需要保存下一节点的地址,当我们删除上一节点时,我们就需要把下一节点的地址赋给头结点指针就行啦,如下图所示,我们把head,free掉,此时head的指针就应该指向next处,这样就可以进行删除啦!

    在这里插入图片描述

    void QueuePop(Queue* pq)
    {
    	assert(pq);
    	assert(!QueueEmpty(pq));
    
    	if (pq->phead->next == NULL)
    	{
    		free(pq->phead);
    		pq->phead = pq->ptail = NULL;
    	}
    	else
    	{
    		QNode* next = pq->phead->next;
    		free(pq->phead);
    		pq->phead = next;
    	}
    	pq->size--;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    😳队列的判空代码实现及其讲解

    判空代码的实际过程其实是这样的,当头指针和尾指针都是空的时候,它就是空啦!!

    bool QueueEmpty(Queue* pq)
    {
    	assert(pq);
    
    	return pq->phead == NULL
    		&& pq->ptail == NULL;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    😳队列的全部代码的实现

    queue.h

    #pragma once
    #include
    #include
    #include
    #include
    
    typedef int	QDatatype;
    typedef struct QueueNode
    {
    	struct QueueNode* next;
    	QDatatype data;
    }QNode;
    
    typedef struct Queue
    {
    	QNode* phead;
    	QNode* ptail;
    	int size;
    }Queue;
    
    void QueueInit(Queue* pq); 
    void QueueDestroy(Queue* pq);
    void QueuePush(Queue* pq, QDatatype x); 
    void QueuePop(Queue* pq);
    QDatatype QueueFront(Queue* pq);
    QDatatype QueueBack(Queue* pq);
    int QueueSize(Queue* pq);
    bool QueueEmpty(Queue* pq);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    queue.c

    #define _CRT_SECURE_NO_WARNINGS 1
    #include "Queue.h"
    
    void QueueInit(Queue* pq)
    {
    	assert(pq);
    	pq->phead = NULL;
    	pq->ptail = NULL;
    	pq->size = 0;
    }
    void QueueDestroy(Queue* pq)
    {
    	assert(pq);
    	QNode* cur = pq->phead;
    	while (cur)
    	{
    		QNode* next = cur->next;
    		free(cur);
    		cur = next;
    	}
    	pq->phead = pq->ptail = NULL;
    	pq->size = 0;
    
    }
    void QueuePush(Queue* pq, QDatatype x)
    {
    	assert(pq);
    
    	QNode* newnode = (QNode*)malloc(sizeof(QNode));
    	if (newnode == NULL)
    	{
    		perror("malloc fail\n");
    		return;
    	}
    	newnode->data = x;
    	newnode->next = NULL;
    	if (pq->ptail == NULL)
    	{
    		assert(pq->phead == NULL);
    		pq->phead = pq->ptail = newnode;
    	}
    	else
    	{
    		pq->ptail->next = newnode;
    		pq->ptail = newnode;
    	}
    	pq->size++;
    }
    
    void QueuePop(Queue* pq)
    {
    	assert(pq);
    	assert(!QueueEmpty(pq));
    
    	if (pq->phead->next == NULL)
    	{
    		free(pq->phead);
    		pq->phead = pq->ptail = NULL;
    	}
    	else
    	{
    		QNode* next = pq->phead->next;
    		free(pq->phead);
    		pq->phead = next;
    	}
    	pq->size--;
    }
    QDatatype QueueFront(Queue* pq)
    {
    	assert(pq);
    	assert(!QueueEmpty(pq));
    
    	return pq->phead->data;
    }
    QDatatype QueueBack(Queue* pq)
    {
    	assert(pq);
    	assert(!QueueEmpty(pq));
    
    	return pq->ptail->data;
    }
    int QueueSize(Queue* pq)
    {
    	assert(pq);
    	return pq->size;
    }
    bool QueueEmpty(Queue* pq)
    {
    	assert(pq);
    
    	return pq->phead == NULL
    		&& pq->ptail == NULL;
    	//pq->size == 0
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94

    总结

    我是爱你们的M malloc,如果你觉得这一期对你有帮助你可以一键三连鸭!!!!下一期会继续更细数据结构!!

  • 相关阅读:
    面试经典-Spring篇
    外汇天眼:外汇交易商常见黑心手法大公开!投资务必留意这5种骗局
    【解决】常见反爬总结之SVG映射
    移植 simpleFoc笔记(一)
    使用Python进行自然语言处理(NLP):NLTK与Spacy的比较【第133篇—NLTK与Spacy】
    vue 自定义指令改data中数据
    Windows下安装MySQL8详细教程
    Vue开发实战02-vue项目添加状态管理Vuex,路由router,以及http请求axios
    「C++」论高精度
    [NOIP2012 普及组] 摆花
  • 原文地址:https://blog.csdn.net/m0_64361522/article/details/130916784