【C语言】链式队列的实现

server/2024/9/25 10:32:55/

队列基本概念

首先我们要了解什么是队列,队列里面包含什么。

队列是线性表的一种是一种先进先出(First In Fi Out)的数据结构。在需要排队的场景下有很强的应用性。有数组队列也有链式队列,数组实现的队列时间复杂度太大,一般链式队列应用更为广泛。

队列里面包括队头和队尾。出队列只能在队头出(头删),入队列只能在队尾入(尾插)。

本篇要实现是单向,不带哨兵位,不循环的用链表实现的队列(此种队列应用较为广泛)

队列的定义

包括一个数据和指向下一个节点的指针

typedef int QDataType;
typedef struct QueueNode
{QDataType val;struct QueueNode* next;
}QNode;

对队列的操作

入队列与出队列

如果只有头指针那我们还是需要遍历队列才能找到队列的队尾进行入队列,而且还需要传二级指针。但是如果还有尾指针那就不需要遍历找尾,效率更高,多个指针用结构体封装,只传一级指针即可

当然在执行出入队列前我们应该先把队列初始化,但是由于说清楚为什么不用二级指针和应该有头尾指针,初始化放在后面了。

typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;

考虑到需要计算队列长度,所以在Queue结构中还加了size成员。

具体实现如下

入队列

void QueuePush(Queue* pq, QDataType x)
{assert(pq);//在队尾入,尾插//创建新节点QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->val = x;newnode->next = NULL;//空链表if (QueueEmpty(pq)){pq->phead = pq->ptail = newnode;}else {pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}

此处要考虑队列为空和队列不为空两种情况,队列为空则新插入的节点即为队列的队头和队尾;

队列不为空,则队尾的next指针指向新节点,新节点成为新的队尾。

判空

bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}

出队列

void QueuePop(Queue* pq)
{assert(pq);//零个节点assert(pq->phead);//一个节点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--;
}

出队列要保证队头不能为空,所以要加assert(pq->phead)语句来暴力检查,队列中如果只有一个节点那么释放掉头队头节点后,把队头和队尾都置为空即可;若有多个节点,先要把队头指向的下一个节点存起来,以防释放掉队头后找不到他的下一个节点,然后让原本队头的下一个节点成为新的队头。

初始化

void QueueInit(Queue* pq)
{assert(pq);pq->phead = pq->ptail = NULL;pq->size = 0;
}

取队头数据

QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->val;
}

取队尾数据

QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->ptail);return pq->ptail->val;
}

队列长度

size_t QueueLength(Queue* pq)
{assert(pq);return pq->size;
}

销毁

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<assert.h>
#include<stdbool.h>
#include<stdlib.h>
typedef int QDataType;
typedef struct QueueNode
{QDataType val;struct QueueNode* next;
}QNode;
typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;//初始化
void QueueInit(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);
//入队列
void QueuePush(Queue* pq, QDataType x);
//出队列
void QueuePop(Queue* pq);
//取队头
QDataType QueueFront(Queue* pq);
//取队尾
QDataType QueueBack(Queue* pq);
//队列长度
size_t QueueLength(Queue* pq);

函数定义

#include"Queue.h"
//初始化
void QueueInit(Queue* pq)
{assert(pq);pq->phead = 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 x)
{assert(pq);//在队尾入,尾插//创建新节点QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->val = x;newnode->next = NULL;//空链表if (QueueEmpty(pq)){pq->phead = pq->ptail = newnode;}else {pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}
//出队列
void QueuePop(Queue* pq)
{assert(pq);//零个节点assert(pq->phead);//一个节点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--;
}
//判空
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}
//取队头
QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->val;
}
//取队尾
QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->ptail);return pq->ptail->val;
}
//队列长度
size_t QueueLength(Queue* pq)
{assert(pq);return pq->size;
}

测试

#include"Queue.h"
void test()
{Queue pq;QueueInit(&pq);QueuePush(&pq, 1);QueuePush(&pq, 2);QueuePush(&pq, 3);QueuePush(&pq, 4);while (!QueueEmpty(&pq)){printf("%d ", QueueFront(&pq));QueuePop(&pq);}QueueDestroy(&pq);
}
int main()
{test();return 0;
}

欢迎各位大佬一起学习交流~

有不当之处欢迎指正~


http://www.ppmy.cn/server/93812.html

相关文章

C++从入门到起飞之——类的定义实例化 全方位剖析!

个人主页&#xff1a;秋风起&#xff0c;再归来~ C从入门到起飞 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c;律己则安&#xff01; 目录 1.类的定义 1.1、类定义格式 1.2、访问限定符 1.3、类域 2.实例化 2.…

【嵌入式】嵌入式软硬件开发中常见的面试题,涉及硬件、电子基础知识、算法、C/C++、Linux、实时操作系统、计算机网络和通信、bug排查、git版本控制(持续更新中)

嵌入式开发中常见的面试题。从事嵌入式开发需要掌握的软硬件知识需要非常全面&#xff0c;本文整理了一些面试过程中常见的高频问题及其参考答案。涉及硬件、电子基础知识、算法、C/C、Linux、实时操作系统、计算机网络和通信、bug排查、git版本控制&#xff08;持续更新中&…

【QT】Qt 窗口 (QMainWindow)

Qt 窗口 一、菜单栏1. 创建菜单栏并添加菜单2. 创建菜单项3. 综合示例 二、工具栏1. 创建工具栏2. 设置停靠位置3. 设置浮动属性4. 综合示例 三、状态栏1. 状态栏的创建2. 在状态栏中显示实时消息3. 在状态栏中显示永久消息 四、浮动窗口1. 浮动窗口的创建2. 设置停靠的位置 五…

【python】最新版小红书js逆向拿到数据,非常详细教程(附完整代码)

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

2024年 Java 面试八股文(20w字)

> &#x1f345;我是小宋&#xff0c; 一个只熬夜但不秃头的Java程序员。 > &#x1f345;关注我&#xff0c;带你**过面试,读源码**。提升简历亮点&#xff08;14个demo&#xff09; > &#x1f345;我的面试集已有12W 浏览量。 > &#x1f30f;号…

Python酷库之旅-第三方库Pandas(003)

目录 一、用法精讲 4、pandas.read_csv函数 4-1、语法 4-2、参数 4-3、功能 4-4、返回值 4-5、说明 4-6、用法 4-6-1、创建csv文件 4-6-2、代码示例 4-6-3、结果输出 二、推荐阅读 1、Python筑基之旅 2、Python函数之旅 3、Python算法之旅 4、Python魔法之旅 …

【Python】从基础到进阶(二):了解Python语言基础以及数据类型转换、基础输入输出

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、引言二、基本数据类型转换1. 隐式转换2. 显式转换 三、基本输入输出1. 输入&#xff08;input&#xff09;2. 输出&#xff08;print&#xff09;3. 案例&#xff1a;输入姓名、年龄、身高以及体重&#xff0c;计算BMI指…

C++:C++入门基础|命名空间|输入输出

欢迎来到HarperLee的学习笔记&#xff01; 博主主页传送门&#xff1a; HarperLee的博客主页! 想要一起进步的uu来后台哦&#xff01; 一、什么是C? 在此之前&#xff0c;我们所学习的C语言是一种结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&a…