C语言 队列的实现全解析
作者:_奇奇
队列(Queue)与栈一样,是一种线性存储结构,它具有如下特点:队列中的数据元素遵循“先进先出”(First In First Out)的原则,简称FIFO结构。在队尾添加元素,在队头删除元素
队列的实现
基本概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头
队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低需要挪动数据O(N)。而链表结构头删只需要O(1)。尾插定义一个尾指针,也只需要O(1)。
创建结构体
这是一个嵌套结构体。
实参q的地址传给了形参pq。pq就是一个指向结构体Queue的指针。Queue里面的head是指向队列对头的指针,tail是指向队尾的指针。
int main() { //创建结构体变量q //需要传q的地址过去。 Queue q; return 0; }
定义一个尾指针tail方便入队的尾插。头指针head方便出队时的头删。
typedef int QDataType; //节点结构体 typedef struct QueueNode { QDataType data; struct QueueNode* next; }QNode; //头指针和尾指针的结构体 typedef struct Queue { QNode* head; QNode* tail; }Queue;
初始化结构体
才开始还没有创建队列的空间,所以只需要初始化第一个结构体就ok了。队列初始状态需要对头和队尾指向同一位置,且都是空。
void QueueInit(Queue* pq) { assert(pq); pq->head = pq->tail = NULL; }
销毁队列结构体
这次我把销毁结构体放在初始化结构体的后面,原因是内存泄漏很严重,但是经常会忘记销毁结构体。创建意味着就要销毁,二者对立,所以排在初始化的后面,理所应当。
void QueueDestory(Queue* pq) { assert(pq); QNode* cur = pq->head; while (cur) { QNode* next = cur->next; free(cur); cur = next; } pq->head = pq->tail = NULL; }
入队
入队的时候,会创建新的节点。最好最好把新开的newnode节点初始化。把他的next置为空,方便后期求队列长度函数,和出队函数的循环条件的书写。
void QueuePush(Queue* pq, QDataType x) { assert(pq); QNode* newnode = (QNode*)malloc(sizeof(QNode)); assert(newnode); //下面两个初始化很有必要 newnode->data = x; newnode->next = NULL; if (pq->tail == NULL) { assert(pq->head == NULL); pq->head = pq->tail = newnode; } else { pq->tail->next = newnode; pq->tail = newnode; } }
出队
因为Queue结构体不可能为空,所以需要断言
还需要断言pq->head和tail都不为空。
void QueuePop(Queue* pq) { assert(pq); assert(pq->head && pq->tail); if (pq->head->next == NULL) { free(pq->head); pq->head = pq->tail = NULL; } else { QNode* next = pq->head->next; free(pq->head); pq->head = next; } }
判断队列是否为空
为空返回true,为假返回false
bool QueueEmpty(Queue* pq) { assert(pq); return pq->head == NULL; }
访问对头的值
QDataType QueueFront(Queue* pq) { assert(pq); assert(pq->head); return pq->head->data; }
访问队尾的值
QDataType QueueBack(Queue* pq) { assert(pq); assert(pq->tail); return pq->tail->data; }
返回队列的长度
长度不可能为负数,所以返回类型为size_t
size_t QueueSize(Queue* pq) { assert(pq); QNode* cur = pq->head; size_t size = 0; while (cur) { size++; cur = cur->next; } return size; }
Queue.h
#pragma once #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <assert.h> typedef int QDataType; typedef struct QueueNode { QDataType data; struct QueueNode* next; }QNode; typedef struct Queue { QNode* head; QNode* tail; //size_t size; }Queue; void QueueInit(Queue* pq); void QueueDestory(Queue* pq); void QueuePush(Queue* pq, QDataType x); void QueuePop(Queue* pq); bool QueueEmpty(Queue* pq); size_t QueueSize(Queue* pq); QDataType QueueFront(Queue* pq); QDataType QueueBack(Queue* pq);
Queue.c
#include "Queue.h" void QueueInit(Queue* pq) { assert(pq); pq->head = pq->tail = NULL; } void QueueDestory(Queue* pq) { assert(pq); QNode* cur = pq->head; while (cur) { QNode* next = cur->next; free(cur); cur = next; } pq->head = pq->tail = NULL; } void QueuePush(Queue* pq, QDataType x) { assert(pq); QNode* newnode = (QNode*)malloc(sizeof(QNode)); assert(newnode); newnode->data = x; newnode->next = NULL; if (pq->tail == NULL) { assert(pq->head == NULL); pq->head = pq->tail = newnode; } else { pq->tail->next = newnode; pq->tail = newnode; } } void QueuePop(Queue* pq) { assert(pq); assert(pq->head && pq->tail); if (pq->head->next == NULL) { free(pq->head); pq->head = pq->tail = NULL; } else { QNode* next = pq->head->next; free(pq->head); pq->head = next; } } bool QueueEmpty(Queue* pq) { assert(pq); return pq->head == NULL; } size_t QueueSize(Queue* pq) { assert(pq); QNode* cur = pq->head; size_t size = 0; while (cur) { size++; cur = cur->next; } return size; } QDataType QueueFront(Queue* pq) { assert(pq); assert(pq->head); return pq->head->data; } QDataType QueueBack(Queue* pq) { assert(pq); assert(pq->tail); return pq->tail->data; }
Test.c
void TestQueue() { Queue q; QueueInit(&q); QueuePush(&q, 1); QueuePush(&q, 2); printf("%d ", QueueFront(&q)); QueuePop(&q); QueuePush(&q, 3); QueuePush(&q, 4); while (!QueueEmpty(&q)) { printf("%d ", QueueFront(&q)); QueuePop(&q); } printf("\n"); } int main() { TestQueue(); return 0; }
到此这篇关于C语言 队列的实现全解析的文章就介绍到这了,更多相关C语言 队列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!