• 数据结构【队列】


    (一)队列定义

    队列是一种常用的数据结构,也是一种操作受限制的线性表,特点是只允许在表的头部进行删除操作,在表的尾部进行插入操作,队列具有先进先出FIFO(First In First Out)。

    入队列:进行插入操作的一端称为队尾
    出队列:进行删除操作的一端称为队头

    我们实现可以用数组和链表结构实现,但使用链表更优,如果去用数组实现啊,出队列在数组头上出数据,效率会很低 ,需要挪动n次,时间复杂度为O(N)。

    (二)队列实现

    (1)创建结构体

    typedef int QDataType;
    typedef struct QueueNode
    {
    	QDataType data;
    	struct QueueNode* next;
    }QNode;
    typedef struct Queue
    {
    	QNode* head;
    	QNode* tail;
    	int size;
    }Queue;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    我们要创建两个结构体,一个表示链式结构,即队列,第二个是队列的结构。
    先使用typedef int QDateType,是为了方便改类型,在结构体里创建2个成员变量,分别表示结点的数据域和指针域,之后创建队列里的结构体,在里面创建两个指针变量分别指向队列的头部和尾部,size记录队列的个数。

    (2)具体函数实现及解析

    1.1 初始化队列

    void QueueInit(Queue* qq)//队列初始化
    {
    	assert(qq);
    	qq->head = qq->tail = NULL;
    	qq->size = 0;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    初始化队列,传一级指针改变的是结构体,只需要结构体指针,qq是不能为空的,所以需要断言防止人为穿空,把头指针和尾指针置空,size置0。

    1.2入队列

    void QueuePush(Queue* qq, QDataType x)//入队列
    {
    	assert(qq);
        QNode* newnode = (QNode*)malloc(sizeof(QNode));
    	if (newnode == NULL)
    	{
    		perror("malloc fail");
    	}
    	newnode->data = x;
    	newnode->next = NULL;
    	if (qq->tail == NULL)
    	{
    		qq->head = qq->tail = newnode;
    	}
    	else
    	{
    		qq->tail->next = newnode;
    		qq->tail = qq->tail->next;
    	}
    	qq->size++;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    入队列其实就是尾插,先malloc申请一个结点,再判断是否为空,再把结点数据域和指针域分别给上x和空,再进行尾插:判断尾或者头是否为空,为空则把它们指向新节点,反之,把新节点链在尾部,并更新尾部,最后插入完把size++。

    1.3出队列

    void QueuePop(Queue* qq)//出队列
    {
    	assert(qq);
    	assert(!QueueEmpty(qq));
    	if (qq->head->next == NULL)
    	{
    		free(qq->head);
    		qq->head = qq->tail = NULL;
    	}
    	else
    	{
    		QNode* del = qq->head;
    		qq->head = qq->head->next;
    		free(del);
    	}
    	qq->size--;
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    出队列是进行头删,除了断言qq是否为空,还要判断整个队列是否为空,空的时候不能删。头删如果只有一个结点,直接free,并把头和尾置空;否则先把头部存在del指针变量中,再更新头结点,释放del。最后size个数–。

    1.4取队首元素

    QDataType QueueFront(Queue* qq)//取队列首元素
    {
    	assert(qq);
    	assert(!QueueEmpty(qq));
    	return qq->head->data;
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    取队首也需要断言,直接返回头部指向的数据。

    1.5取队尾元素

    QDataType QueueBack(Queue* qq)//取队列尾元素
    {
    	assert(qq);
    	assert(!QueueEmpty(qq));
    	return qq->tail->data;
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    取队尾直接返回尾部指向的数据。

    1.6返回队列个数

    int QueueSize(Queue* qq)//返回队列个数
    {
    	assert(qq);
    	return qq->size;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    返回队列个数,返回qq指向的个数。

    1.7判断是否为空

    bool QueueEmpty(Queue* qq)//判断是否为空
    {
    	assert(qq);
    	return qq->head == NULL &&qq->tail == NULL;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    判断是否为空,直接返回head和tail同时为空,如果同时为空返回true,有一个不为空返回false。

    1.8销毁队列

    void QueueDestroy(Queue* qq)//销毁队列
    {
    	assert(qq);
    	QNode* cur = qq->head;
    	while (cur)
    	{
    		QNode* del = cur;
    		cur = cur->next;
    		free(del);
    	}
    	qq->head = qq->tail = NULL;
    	qq->size = 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    队列销毁需要把头指针存到cur中,用while循环,把cur存到del指针变量中,更新cur,并释放掉del。最后把头指针和尾指针同时置为空,size置0。

    (三)队列实现代代码

    (1)Queue.c

    #include"Queue.h"
    void QueueInit(Queue* qq)//队列初始化
    {
    	assert(qq);
    	qq->head = qq->tail = NULL;
    	qq->size = 0;
    
    }
    
    void QueuePush(Queue* qq, QDataType x)//入队列
    {
    	assert(qq);
        QNode* newnode = (QNode*)malloc(sizeof(QNode));
    	if (newnode == NULL)
    	{
    		perror("malloc fail");
    	}
    	newnode->data = x;
    	newnode->next = NULL;
    	if (qq->tail == NULL)
    	{
    		qq->head = qq->tail = newnode;
    	}
    	else
    	{
    		qq->tail->next = newnode;
    		qq->tail = qq->tail->next;
    	}
    	qq->size++;
    }
    
    void QueuePop(Queue* qq)//出队列
    {
    	assert(qq);
    	assert(!QueueEmpty(qq));
    	if (qq->head->next == NULL)
    	{
    		free(qq->head);
    		qq->head = qq->tail = NULL;
    	}
    	else
    	{
    		QNode* del = qq->head;
    		qq->head = qq->head->next;
    		free(del);
    	}
    	qq->size--;
    	
    }
    
    QDataType QueueFront(Queue* qq)//取队列首元素
    {
    	assert(qq);
    	assert(!QueueEmpty(qq));
    	return qq->head->data;
    
    
    }
    
    QDataType QueueBack(Queue* qq)//取队列尾元素
    {
    	assert(qq);
    	assert(!QueueEmpty(qq));
    	return qq->tail->data;
    
    }
    
    int QueueSize(Queue* qq)//返回队列个数
    {
    	assert(qq);
    	return qq->size;
    }
    
    bool QueueEmpty(Queue* qq)//判断是否为空
    {
    	assert(qq);
    	return qq->head == NULL &&qq->tail == NULL;
    
    }
    
    void QueueDestroy(Queue* qq)//销毁队列
    {
    	assert(qq);
    	QNode* cur = qq->head;
    	while (cur)
    	{
    		QNode* del = cur;
    		cur = cur->next;
    		free(del);
    	}
    	qq->head = qq->tail = NULL;
    	qq->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

    (2)Queue.h

    #pragma once
    #include
    #include
    #include
    #include
    typedef int QDataType;
    typedef struct QueueNode
    {
    	QDataType data;
    	struct QueueNode* next;
    }QNode;
    typedef struct Queue
    {
    	QNode* head;
    	QNode* tail;
    	int size;
    }Queue;
    void QueueInit(Queue* qq);//队列初始化
    
    void QueuePush(Queue* qq,QDataType x);//入队列
    
    void QueuePop(Queue* qq);//出队列
    
    QDataType QueueFront(Queue* qq);//取队列首元素
    
    QDataType QueueBack(Queue* qq);//取队列尾元素
    
    int QueueSize(Queue* qq);//返回队列个数
    
    bool QueueEmpty(Queue* qq);//判断是否为空
    
    void QueueDestroy(Queue* qq);//销毁队列
    
    
    • 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

    (3)test.c

    #include"Queue.h"
    void test()
    {
    	Queue q;
    	QueueInit(&q);
    	QueuePush(&q, 9);
    	QueuePush(&q, 8);
    
    	printf("%d ", QueueFront(&q));
    	QueuePop(&q);
    
    	QueuePush(&q, 7);
    	QueuePush(&q, 6);
    
    	printf("%d\n", QueueEmpty(&q));
    	printf("%d\n", QueueFront(&q));
    	printf("%d\n", QueueBack(&q));
    
    	while (!QueueEmpty(&q))
    	{
    		printf("%d ", QueueFront(&q));
    		QueuePop(&q);
    	}
    	printf("\n");
    
    	printf("%d\n", QueueSize(&q));
    }
    int main()
    {
    	test();
    	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
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    (四)队列测试结果

    在这里插入图片描述

  • 相关阅读:
    检测滑动是否到达底部
    008:字符串交换,输入两个长度为4的字符串,交换这两个字符串的前两个字符后输出
    SpringCloud学习
    关于对于Java中Entity以及VO,以及DTO中Request对象序列化的学习
    TypeScript类的使用
    jpa整合sharding-jdbc不分库分表(包括id主键生成策略的使用)
    Go类型全解:常量与变量大全!
    8-2插入排序-折半插入排序
    js+html实现打字游戏v1
    2101. 引爆最多的炸弹;752. 打开转盘锁;1234. 替换子串得到平衡字符串
  • 原文地址:https://blog.csdn.net/m0_59292239/article/details/127847566