• 数据结构——看完这篇保证你学会队列


    一、队列的概念

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

    在这里插入图片描述

    二、队列的实现方式

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

    三、队列所需要的接口

    //初始化
    void QueueInit(Queue* pq);
    
    //销毁
    void QueueDestory(Queue* pq);
    
    //入队
    void QueuePush(Queue* pq, Queuedatatype x);
    
    //出队
    void QueuePop(Queue* pq);
    
    //获取队头元素
    Queuedatatype QueueFront(Queue* pq);
    
    //获取队尾元素
    Queuedatatype 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

    四、接口的详细实现

    4.1初始化

    初始化:我们需要将pq->phead和pq->ptail都置为NULL,并且将pq->size置为0;

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

    4.2销毁

    销毁:首先定义一个cur指针保存头节点phead的地址,接下来利用cur!=NULL使得循环往下走,在循环内定义一个next的指针来更新地址,并且用free来释放内存,出循环后,将pq->phead,pq->ptail都置为NULL,并且将pq->size置为0。

    void QueueDestory(Queue* pq)
    {
    	assert(pq);
    	Queuenode* cur = pq->phead;
    	while (cur)
    	{
    		Queue* 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

    在这里插入图片描述

    4.3入队

    入队:入队有两种情况。第一种,队内无其他元素;第二种,队内有其他元素。
    ①、队内无其他元素:直接让pq->phead = pq->ptail = newnode;
    在这里插入图片描述
    ②、队内有其它元素:如果队列不为NULL,我们需要让pq->ptail->next指向newnode,并且最后再让pq->ptail指向newnode.
    在这里插入图片描述

    oid QueuePush(Queue* pq, Queuedatatype x)
    {
    	assert(pq);
    	Queuenode* newnode = (Queuenode*)malloc(sizeof(Queuenode));
    	if (newnode == NULL)
    	{
    		perror("malloc fail");
    		return;
    	}
    	newnode->data = x;
    	newnode->next = NULL;
    	//队内无其它元素
    	if (pq->phead == NULL)
    	{
    		assert(pq->ptail == 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
    • 25
    • 26
    • 27

    4.5出队

    出队:出队列大体上分为两种情况:有节点和无节点。
    ①、如果队列中没有节点,就不能进行出队操作,我们这时可以用assert(!QueueEmpty(pq)); 来进行判断。
    ②、队列中有节点时,又可以分为一个节点和多个节点之分,如果队列中只有一个节点时,我们直接用free 置空;如果队列中有多个节点时,首先、创建一个next用来保存phead的下一个节点的地址,我们free(phead),再让phead等于我们的next。

    // 出队
    void QueuePop(Queue * pq)
    {
    	assert(pq);
    	assert(!QueueEmpty(pq));
    	//一个节点
    	if (pq->phead->next == NULL)
    	{
    		free(pq->phead);
    		pq->phead = pq->ptail=NULL;
    	}
    	//多个节点
    	else
    	{
    		//头删
    		Queuenode* 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
    • 19
    • 20
    • 21

    4.6获取队头元素

    //获取队头元素
    Queuedatatype QueueFront(Queue* pq)
    {
    	assert(pq);
    	return pq->phead->data;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4.7获取队尾元素

    //获取队尾元素
    Queuedatatype QueueBack(Queue* pq)
    {
    	assert(pq);
    	return pq->ptail->data;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4.8获取队列元素个数

    //获取队列元素个数
    int Queuesize(Queue* pq)
    {
    	assert(pq);
    	return pq->size;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    4.9判空

    如果pq->size==0时,便证明队列为NULL。

    //判空
    bool QueueEmpty(Queue* pq)
    {
    	assert(pq);
    	return pq->size == 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    五、完整代码

    5.1Queue.h

    #pragma once
    #include
    #include
    #include
    #include
    
    typedef int Queuedatatype;
    //定义队列结构
    typedef struct Queuenode
    {
    	struct Queuenode* next;
    	Queuedatatype data;
    }Queuenode;
    
    
    typedef struct Queue
    {
    	Queuenode* phead;
    	Queuenode* ptail;
    	int size;
    }Queue;
    
    //初始化
    void QueueInit(Queue* pq);
    
    //销毁
    void QueueDestory(Queue* pq);
    
    //入队
    void QueuePush(Queue* pq, Queuedatatype x);
    
    //出队
    void QueuePop(Queue* pq);
    
    //获取队头元素
    Queuedatatype QueueFront(Queue* pq);
    
    //获取队尾元素
    Queuedatatype 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
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    5.2Queue.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 QueueDestory(Queue* pq)
    {
    	assert(pq);
    	Queuenode* cur = pq->phead;
    	while (cur)
    	{
    		Queue* next = cur->next;
    		free(cur);
    		cur = next;
    	}
    	pq->phead = pq->ptail = NULL;
    	pq->size = 0;
    }
    
    //入队
    void QueuePush(Queue* pq, Queuedatatype x)
    {
    	assert(pq);
    	Queuenode* newnode = (Queuenode*)malloc(sizeof(Queuenode));
    	if (newnode == NULL)
    	{
    		perror("malloc fail");
    		return;
    	}
    	newnode->data = x;
    	newnode->next = NULL;
    
    	if (pq->phead == NULL)
    	{
    		assert(pq->ptail == NULL);
    		pq->phead = pq->ptail = newnode;
        }
    	//链接
    	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
    	{
    		//头删
    		Queuenode* next = pq->phead->next;
    		free(pq->phead);
    		pq->phead = next;
    	}
    	pq->size--;
    }
    
    //获取队头元素
    Queuedatatype QueueFront(Queue* pq)
    {
    	assert(pq);
    	return pq->phead->data;
    }
    
    //获取队尾元素
    Queuedatatype QueueBack(Queue* pq)
    {
    	assert(pq);
    	return pq->ptail->data;
    }
    
    //获取队列元素个数
    int Queuesize(Queue* pq)
    {
    	assert(pq);
    	return pq->size;
    }
    
    //判空
    bool QueueEmpty(Queue* pq)
    {
    	assert(pq);
    	return 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
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101

    5.3test.c

    #define _CRT_SECURE_NO_WARNINGS 1
    #include"Queue.h"
    void test1()
    {
    	Queue q;
    	QueueInit(&q);
    	QueuePush(&q, 1);
    	QueuePush(&q, 2);
    	QueuePush(&q, 3);
    	QueuePush(&q, 4);
    	printf("Size:%d\n", Queuesize(&q));
    	while (!QueueEmpty(&q))
    	{
    		printf("%d ", QueueFront(&q));
    		QueuePop(&q);
    	}
    
    }
    int main()
    {
    	test1();
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
  • 相关阅读:
    【华为机试真题 JAVA】工号不够用了怎么办-100
    NC202475 树上子链
    弹簧系统三维可视化
    【定义】矩阵
    Git 的暂存区(staging area)理解
    MongoDB 对索引的创建查询修改删除 附代码
    干货|数据资产评估的基本方法和选择方法
    模拟电路知识点总结(极简略版)--基本放大电路
    MyBatis框架
    ElementUI浅尝辄止23:Loading 加载
  • 原文地址:https://blog.csdn.net/qq_64034271/article/details/132843147