队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头,如下图。
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
这个思路是,先创建一个节点用来存储数据,也就是一个单链表,而这里需要头和尾,也就是尾进头出,如1 2 3 4 5 6 7 这样进去,出去也是1 2 3 4 5 6 7,顺序不会改变,所以这里又定义了一个结构用来存储头和尾以及有效的数据,方便后续操作,初始化这里就是把头和尾指向空,当有数据进来时才指向新的节点,销毁就是把单链表释放销毁,而刚开始使用存储链表的头和尾的结构体,因为是局部变量,只需要把头和尾的指针置空,当函数销毁时,这个结构体也会销毁,代码如下。
- 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)
- {
- 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 data)
- {
- assert(pq);
- QNode* newnode = (QNode*)malloc(sizeof(QNode));
- if (newnode == NULL)
- {
- perror("malloc fail");
- return;
- }
- newnode->data = data;
- 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;
- }
-
- // 检测队列是否为空,如果为空返回非零结果,如果非空返回0
- bool QueueEmpty(Queue* pq)
- {
- assert(pq);
- return pq->size==0;
- }
这个就是测试各个函数,也就是插入1 2 3 4 5 6 7然后读取下有几个数据,然后把尾部数据打印,利用之前写的判断函数也就可以直接用while函数去进行出队数据并且打印,然后队里数据全部出完后,再去取数据打印和删除,会直接报错,代码和测试结果如图。
- #define _CRT_SECURE_NO_WARNINGS 1
- #include "QL.h"
-
- void TestQueue()
- {
- Queue q;
-
- QueueInit(&q);
- QueuePush(&q, 1);
- QueuePush(&q, 2);
- QueuePush(&q, 3);
- QueuePush(&q, 4);
- QueuePush(&q, 5);
- QueuePush(&q, 6);
- QueuePush(&q, 7);
- printf("size:%d\n", QueueSize(&q));
- printf("%d\n", QueueBack(&q));
- while (!QueueEmpty(&q))
- {
- printf("%d ", QueueFront(&q));
- QueuePop(&q);
- }
- printf("%d ", QueueFront(&q));
- QueuePop(&q);
- QueueDestroy(&q);
- }
-
- int main()
- {
- TestQueue();
- return 0;
- }
- #define _CRT_SECURE_NO_WARNINGS 1
- #include "QL.h"
-
- void TestQueue()
- {
- Queue q;
-
- QueueInit(&q);
- QueuePush(&q, 1);
- QueuePush(&q, 2);
- QueuePush(&q, 3);
- QueuePush(&q, 4);
- QueuePush(&q, 5);
- QueuePush(&q, 6);
- QueuePush(&q, 7);
- printf("size:%d\n", QueueSize(&q));
- printf("%d\n", QueueBack(&q));
- while (!QueueEmpty(&q))
- {
- printf("%d ", QueueFront(&q));
- QueuePop(&q);
- }
- printf("%d ", QueueFront(&q));
- QueuePop(&q);
- QueueDestroy(&q);
- }
-
- int main()
- {
- TestQueue();
- return 0;
- }
- #define _CRT_SECURE_NO_WARNINGS 1
- #include "QL.h"
-
- // 初始化队列
- void QueueInit(Queue* pq)
- {
- assert(pq);
- pq->phead = NULL;
- pq->ptail = NULL;
- pq->size = 0;
- }
-
- // 队尾入队列
- void QueuePush(Queue* pq, QDataType data)
- {
- assert(pq);
- QNode* newnode = (QNode*)malloc(sizeof(QNode));
- if (newnode == NULL)
- {
- perror("malloc fail");
- return;
- }
- newnode->data = data;
- 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;
- }
-
- // 检测队列是否为空,如果为空返回非零结果,如果非空返回0
- bool QueueEmpty(Queue* pq)
- {
- assert(pq);
- return 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;
- }
- #pragma once
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <stdbool.h>
- 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 QueuePush(Queue* pq, QDataType data);
- // 队头出队列
- void QueuePop(Queue* pq);
- // 获取队列头部元素
- QDataType QueueFront(Queue* pq);
- // 获取队列队尾元素
- QDataType QueueBack(Queue* pq);
- // 获取队列中有效元素个数
- int QueueSize(Queue* pq);
- // 检测队列是否为空,如果为空返回非零结果,如果非空返回0
- bool QueueEmpty(Queue* pq);
- // 销毁队列
- void QueueDestroy(Queue* pq);