【植物大战数据结构|植物大战 队列 —— 纯C】“ 江天一色无纤尘,皎皎空中孤月轮。 ”猛戳订阅 纯C详解数据结构专栏
这里是目录
- 队列的实现
-
- 基本概念
- 创建结构体
- 初始化结构体
- 销毁队列结构体
- 入队
- 出队
- 判断队列是否为空
- 访问对头的值
- 访问队尾的值
- 返回队列的长度
- Queue.h
- Queue.c
- Test.c
队列的实现 基本概念 队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出
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 = https://www.it610.com/article/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
#include
#include
#include 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 = https://www.it610.com/article/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;
}
推荐阅读
- Java进阶|Java进阶学习——数据结构基础(二)
- 数据结构|小肥柴慢慢手写数据结构(C篇)(3-2 Stack应用举例)
- 数据结构|数据结构与算法入门前必读
- 数据结构|索引的数据结构
- 数据结构|数据结构与算法一篇帮助你吃下KMP算法
- 【数据结构·水滴计划】|【数据结构】一篇文章带你彻底吃透·算法复杂度
- JavaSE|Java入门了解
- JavaSE|JavaSE基本语法(下),你确定都懂了吗()
- JavaSE|JavaSE基本语法(上),你确定都懂了吗()