目录
概念
队列是一种特殊的线性表,遵循先进先出的原则,一端进行插入,另一端进行删除,插入的一端称为队尾,删除的一端称为队头。
头部的删除效率链表比顺序表的高,顺序表需要挪动数据,时间复杂度为O(N),链表时间复杂度为O(1),所以选择链表来实现队列效率更高。
思路和源代码
思路
链表每个结点的创建需要创建一个结构体,为了高效率的访问和使用头结点和尾结点,创建一个新的结构体与节点结构体发生关系,来记录头结点和尾结点的地址,其次就是各个接口的实现,新的结构体的初始化,创建一个结点,队尾入队列(尾部的插入),队头出队列(头部的删除),获取元素个数,判断是否为空,获取头结点的值,获取尾结点的值,销毁队列。
源代码
主题框架(Queue.h)
#pragma once #include <stdio.h> #include <stdlib.h> #include <assert.h> #include <stdbool.h> typedef int DataType; /*每个节点的结构体,用单链表不用双链表或者是带头双向循环链表是因为实现队列单链表就足够了,能花20块钱买的东西,我才不要花50块钱来买*/ typedef struct Queue { DataType data; struct Queue* next; }QNode; /*队列操作的是头和尾,用一个结构体来记录*/ typedef struct Qlist { QNode* head; QNode* tail; int sz; }Queue; /*初始化*/ void QueueInit(Queue* pq); /*销毁*/ void Destroy(Queue* pq); /*插入*/ void QueuePush(Queue* pq, DataType x); /*删除*/ void QueuePop(Queue* pq); /*判断是否为空*/ bool QueueEmpty(Queue* pq); /*尾元素*/ DataType QueueBack(Queue* pq); /*头元素*/ DataType QueueFront(Queue* pq); /*元素个数*/ int QueueSize(Queue* pq);
各个接口的实现
初始化
/*初始化*/ void QueueInit(Queue* pq) { assert(pq); pq->head = pq->tail = NULL; pq->sz = 0; }
创建一个结点
/*创建一个结点*/ QNode* BuyNode(Datatype x) { QNode* ptr = (QNode*)malloc(sizeof(QNode)); if (ptr == NULL) { perror("malloc fail"); exit(-1); } ptr->data = x; ptr->next = NULL; return ptr; }
队尾入队列
/*尾部插入*/ void QueuePush(Queue* pq, DataType x) { assert(pq); if (pq->tail == NULL) { pq->head = pq->tail = BuyNode(x); } else { pq->tail->next = BuyNode(x); pq->tail = pq->tail->next; } pq->sz++; }
队头出队列
/*头部的删除*/ void QueuePop(Queue* pq) { assert(pq); assert(!QueueEmpty(pq)); QNode* del = pq->head; if (pq->head == pq->tail)/*只有一个节点,头改变尾也跟着改变*/ { free(del); pq->head = pq->tail = NULL; } else/*不与尾结点重合的其他节点删除*/ { pq->head = del->next;/*新的头*/ free(del); } del = NULL;/*好的习惯,置空*/ pq->sz--;/*元素个数-1*/ }
判断队列是否为空
/*判断是否为空*/ bool QueueEmpty(Queue* pq) { assert(pq); return pq->head == NULL && pq->tail == NULL; }
获取队列元素个数
/*获取元素个数*/ int QueueSize(Queue* ps) { assert(ps); return ps->sz; }
获取队列队尾元素
/*尾元素*/ DataType QueueBack(Queue* pq) { assert(pq); return pq->tail->data; }
获取队列队头元素
/*头元素*/ DataType QueueFront(Queue* pq) { assert(pq); return pq->head->data; }
销毁
/*销毁*/ void Destroy(Queue* pq) { assert(pq); QNode* cur = pq->head; while (cur != NULL) { QNode* next = cur->next; free(cur); cur = next; } pq->head = pq->tail = NULL; }
测试队列(main函数所在的源文件test.c)
#include "Queue.h" void test() { Queue q; QueueInit(&q); QueuePush(&q, 1); QueuePush(&q, 2); QueuePush(&q, 3); printf("%d ", QueueFront(&q)); QueuePop(&q); printf("%d ", QueueFront(&q)); QueuePop(&q); QueuePush(&q, 4); QueuePush(&q, 4); QueuePush(&q, 4); while (!QueueEmpty(&q)) { printf("%d ", QueueFront(&q)); QueuePop(&q); } printf("\n"); Destroy(&q); } int main() { test(); return 0; }
各个接口的实现整合
#define _CRT_SECURE_NO_WARNINGS #include "Queue.h" /*初始化*/ void QueueInit(Queue* pq) { assert(pq); pq->head = pq->tail = NULL; pq->sz = 0; } /*创建一个节点*/ QNode* BuyNode(x) { QNode* ptr = (QNode*)malloc(sizeof(QNode)); if (ptr == NULL) { perror("malloc fail"); exit(-1); } ptr->data = x; ptr->next = NULL; return ptr; } /*销毁*/ void Destroy(Queue* pq) { assert(pq); QNode* cur = pq->head; while (cur != NULL) { QNode* next = cur->next; free(cur); cur = next; } pq->head = pq->tail = NULL; } /*尾部插入*/ void QueuePush(Queue* pq, DataType x) { assert(pq); if (pq->tail == NULL) { pq->head = pq->tail = BuyNode(x); } else { pq->tail->next = BuyNode(x); pq->tail = pq->tail->next; } pq->sz++; } /*头部的删除*/ void QueuePop(Queue* pq) { assert(pq); assert(!QueueEmpty(pq)); QNode* del = pq->head; if (pq->head == pq->tail)/*只有一个节点,头改变尾也跟着改变*/ { free(del); pq->head = pq->tail = NULL; } else/*不与尾结点重合的其他节点删除*/ { pq->head = del->next;/*新的头*/ free(del); } del = NULL;/*好的习惯,置空*/ pq->sz--;/*元素个数-1*/ } /*判断是否为空*/ bool QueueEmpty(Queue* pq) { assert(pq); return pq->head == NULL && pq->tail == NULL; } /*获取元素个数*/ int QueueSize(Queue* ps) { assert(ps); return ps->sz; } /*尾元素*/ DataType QueueBack(Queue* pq) { assert(pq); return pq->tail->data; } /*头元素*/ DataType QueueFront(Queue* pq) { assert(pq); return pq->head->data; }