队列 手把手教会你
本文介绍了队列(Queue)的数据结构实现。队列采用先进先出(FIFO)原则,类比排队打菜场景。使用单链表实现队列时,通过结构体同时记录队头和队尾指针,以支持快速入队和出队操作。文章详细讲解了队列的初始化、判空、销毁、入队、出队等核心操作,并提供了完整的C语言实现代码。其中重点说明了尾插入队和头删出队的实现细节,以及如何通过size变量高效统计队列元素数量。队列结构体封装了Head和Tail指针,
·
队列 先进 先出 很公平 排队打菜一样
有对头 和 对尾 就是对单链表 限制或者只去用部分的函数 就不要其他的功能 来使其 具有独特的 属性和 应用场景
现实 比喻 嘉豪 男娘 等
1 为什么非要包一个结构体?因为队列必须同时记住:头在哪、尾在哪,不然没法快速入队、出队。


<stdlib.h> 精简版作用
1. 动态内存:malloc、free、calloc、realloc
2. 程序退出:exit()
3. 类型转换:atoi 字符串转整数、atof 转小数
4. 随机数:rand、srand
5. 工具函数:abs 求绝对值、qsort 排序
一句话:C语言内存分配、随机数、类型转换、程序退出都靠它。
每一个 Node 就是一个排队的人
val 是这个人带的东西
next 是伸手指着下一个人
将结构体变量 看作大哥 下面有小弟 大哥可以指挥小弟
Queue 是总管,手里拿着两个指针,盯着队伍头和队伍尾。
方便 头删 出队列 对头
尾插 入队列 队尾
2 第一个初始化函数 —— 队列初始化
思路:刚创建一个队列,队伍里一个人都没有所以:
头指针、尾指针 都赋值为 NULL

3 判空函数 思路:
只要 head == NULL,说明队伍没人,就是空队列。

return pq->Head ==NULL;
return !pq->Head;z
这里是等价的 但推荐第一种只管 表达式的结果就是返回值 很直观
4 销毁队列 
需要从头开始 来写 一个一个遍历之后 销毁 free

5 入队列
*队列结构体已经把 head 和 tail 包起来了,你传 Queue 就能修改 head 和 tail,根本不需要二级指针!**

尾插 时的 直接使用 记录好的Tail 




6 取数据 对头 队尾 
注意 队列判空
7 求 队列中的人数

细节拉满


------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
接口函数-
#define _CRT_SECURE_NO_WARNINGS 1
#include "queue.h"
//初始化
void QueueInit(Queue* pq) {
assert(pq);
//pq->val = 0; 对里没人 更不可能有东西呀
pq->Head=pq->Tail = NULL;
}
// 还有就是销毁
void QueueDestroy(Queue* pq) {
assert(pq);
Node* cur = pq->Head;
while (cur!=NULL) {
Node* next = cur->next;//记录下个节点
free(cur);//cur无
cur = next;//狸猫换太子
}
pq->Head = pq->Tail = NULL;
}
// 判空
bool EmptyQueue(Queue* pq) {
assert(pq);
return pq->Head ==NULL;
//return !pq->Head;
//return pq->Head !=NULL;
//return pq->Head;
}
// 入队列 尾插
void QueuePush(Queue* pq,QueueDatatype x) {
assert(pq);
//创建新的节点
Node* newnode = (Node*)malloc(sizeof(Node));
if (newnode == NULL) {
perror("malloc error!\n");
return;
}
newnode->val = x;
newnode->next = NULL;
//0 节点
if (pq->Head == NULL) {
pq->Head = pq->Tail = newnode;
}
else//至少一节点 尾插
{
//Node* Ftail = pq->Head;
//while (Ftail->next!=NULL) {
// Ftail = Ftail->next;
//}
//Ftail->next = newnode;
//直接使用
pq->Tail->next = newnode;
pq->Tail = newnode;
}
pq->size++;//666
}
// 出队 头删除
void QueuePop(Queue* pq) {
assert(pq);
assert(!EmptyQueue( pq));
Node*del = pq->Head;
Node* next = pq->Head->next;
free(del);
del = NULL;
pq->Head = next;
if (next == NULL) {
pq->Tail = pq->Head = NULL;
}
pq->size--;///6666
}
//取对头
QueueDatatype GotQHead(Queue* pq) {
assert(pq);
assert(!EmptyQueue(pq));
return pq->Head->val;
}
// 队尾数
QueueDatatype GotQTail(Queue* pq) {
assert(pq);
assert(!EmptyQueue(pq));
return pq->Tail->val;
}
//
// 队列中的数据总数
// 每次新增size都加一 o(1)
int CountQsize(Queue* pq) {
return pq->size;
}
头文件
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
typedef int QueueDatatype;
//单链表实现
typedef struct Node {
QueueDatatype val;//物品
struct Node* next;
}Node; //人
typedef struct Queue {
Node* Head;
int size;
Node* Tail;
}Queue;

更多推荐





所有评论(0)