数据结构漫游记:队列的动态模拟实现(C语言)

ops/2025/1/20 22:38:26/

嘿,各位技术潮人!好久不见甚是想念。生活就像一场奇妙冒险,而编程就是那把超酷的万能钥匙。此刻,阳光洒在键盘上,灵感在指尖跳跃,让我们抛开一切束缚,给平淡日子加点料,注入满满的passion。准备好和我一起冲进代码的奇幻宇宙了吗?Let's go!

我的博客:yuanManGan

我的专栏:C++入门小馆 C言雅韵集 数据结构漫游记  闲言碎语小记坊 题山采玉

目录

队列的理解:

基础数据结构的选取:

队列的模拟实现

队列的结构的定义

队列的初始化

入队

判空

出队

获取队头元素

获取队尾元素

获取元素个数

销毁队列 

测试代码

总结:


 

队列的理解:

队列就跟排队吃饭一样,先排到的人先走,后来的人只能在队尾慢慢排。

我们类比于栈,发现我们的队列它只能从一端入数据,一端出数据。

它依然是一个顺序表,在逻辑结构上是顺序存储,而在物理结构就不一定了。

基础数据结构的选取:

还是和栈一样的问题,我们该使用数组还是链表来模拟实现这个数据结构呢?

先来看看数组:

如果我们在数组一端当作队尾一端当作队头。但是我们了解到数组在头部进行操作的时间复杂度都是O(n),不复合我们对时间复杂度的预期,那我们将队尾和队头互换呢,还不是要对数组的头部进行操作,这样看来数组用来实现队列不是一个好选择。

那我们来试试链表:

同样的我们将 头结点视作队头,尾结点视为队尾,发现无论我们以那个结点为头,那个结点为尾,我们始终逃不掉要对尾结点进行操作,要么尾插要么尾删。有没有什么办法能够让尾部进行操作的时间复杂度降到O(1)呢?

你别说还真有如果我们定义一个指针一直指向尾结点呢,之前我们实现链表时都有这个想法,但因为尾部进行删除时指向尾结点的指针不能找到他的前一个结点,但我们如果实现队列,根本不需要对尾部进行删除操作,所以我们定义一个始终指向尾结点的指针,然后进行尾插操作很显然时间复杂度就降到了O(1)了。

队列的模拟实现

队列的结构的定义

因为队列里面有两个指针,一个指向头结点,一个指向尾结点,我们得先定义结点的结构体,然后两个指针在队列的结构体之中。

typedef int QDataType;
// 链式结构:表示队列 
typedef struct QListNode
{struct QListNode* next;QDataType data;
}QNode

这里定义了一个结点类型是重命名为QNode

然后定义队列的结构

// 队列的结构 
typedef struct Queue
{QNode* front;QNode* rear;
}Queue;

队列的初始化

我们得将队列里面的两个指针先置为空。还得判断不能传入空指针。

// 初始化队列 
void QueueInit(Queue* q)
{assert(q);q->rear = q->front = NULL;
}

入队

入队就是向尾结点加入数据,那如果链表为空呢,我们得特判,让首尾结点都指向新结点

void QueuePush(Queue* q, QDataType data)
{assert(q);QNode* tmp = (QNode*)malloc(sizeof(QNode));if(tmp ==NULL) {	perror("malloc失败\n");exit(1);}tmp->data = data;tmp->next = NULL;if (q->front == NULL) q->front = q->rear = tmp;else{q->rear->next = tmp;q->rear = q->rear->next;}
}

最后要让尾结点等于新的尾结点,不然会死循环

判空

判空这个操作也很简单,当头结点或者是尾结点指向空的时候队列就是空的

bool QueueEmpty(Queue* q)
{assert(q);return q->front == NULL;
}

出队

出队就是删除头结点,如果只有一个结点的时候,就得让头指针和尾指针指向NULL,如果没有结点,就不能进行这个操作就assert一下就好了。

void QueuePop(Queue* q)
{assert(!QueueEmpty(q));if (q->front == q->rear){free(q->front);q->front = q->rear = NULL;}else {QNode* tmp = q->front;q->front = q->front->next;free(tmp);}}

注意删除的时候要用一个变量来暂时接收一下头结点的下一个结点的地址,不然释放了头结点就找不到下一个结点了,对释放了的指针解引用是野指针的行为。

获取队头元素

获取队头和队尾很简单,但要记得assert一下。

QDataType QueueFront(Queue* q)
{assert(!QueueEmpty(q));return q->front->data;
}

获取队尾元素

// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{assert(!QueueEmpty(q));return q->rear->data;
}

获取元素个数

我们如果用遍历来实现获取元素个数,那么时间复杂度就又成了O(n)呢,如果这个操作执行的次数少到也无妨,但如果执行的次数多我还是建议定义结构的时候多定义一个变量size,然后初始化,入队,出队时多进行一下操作即可。

int QueueSize(Queue* q)
{return q->size;
}

销毁队列 

最后一个销毁队列,这个没办法,只能遍历链表呢

void QueueDestroy(Queue* q)
{assert(q);QNode* cur = q->front;while (cur){QNode* next = cur->next;free(cur);cur = next;}q->rear = q->front = NULL;q->size = 0;
}

测试代码

#include"queue.h"void test01()
{Queue pq;QueueInit(&pq);for (int i = 1; i <= 10; i++){QueuePush(&pq, i);}while (QueueSize(&pq))//!QueueEmpty(&pq){printf("队头:%d   队尾:%d\n", QueueFront(&pq), QueueBack(&pq));QueuePop(&pq);}QueueDestroy(&pq);
}
int main()
{test01();return 0;
}

结果

总结:

我们实现的队列,除了销毁时的时间复杂度是O(n),其他都是常数级别的,实现的队列采用的是链表。

完结撒花谢谢大家!


http://www.ppmy.cn/ops/151774.html

相关文章

Flutter ListView进阶:如何实现根据索引值滚动到列表特定位置

在Flutter开发中&#xff0c;ListView是一个非常常用的组件&#xff0c;它允许我们展示一系列的项目。然而&#xff0c;有时候我们需要根据特定的索引值滚动到ListView中的某个项目位置&#xff0c;以便提供更好的用户体验。本文将详细介绍如何在Flutter中实现这一功能。 一、…

c++ string

1 sting 基本概念 string 基本概念 本质&#xff1a;string是c风格的字符串&#xff0c;而string 本质上是一个类string 和char* 的区别&#xff1a; char * 是一个指针 string 是一个类&#xff0c;类内部封装了char*&#xff0c;管理这个字符串&#xff0c;是一个char* 数组…

独立看门狗(IWDG)实验【学习记录】

STM32内部自带了 2个看门狗&#xff1a;独立看门狗&#xff08; IWDG&#xff09;和窗口看门狗 WWDG&#xff09;。 我们将通过按键 WK_UP来喂狗&#xff0c;然后通过 DS0提示复位状态。 10.1 STM32独立看门狗简介 40KHZ低速时钟驱动&#xff0c;是一个内部RC时钟&#xff0…

C语言之装甲车库车辆动态监控辅助记录系统

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 C语言之装甲车库车辆动态监控辅助记录系统 目录 一、前言 1.1 &#xff08;一&#xff09;…

Elasticsearch:Jira 连接器教程第一部分

作者&#xff1a;来自 Elastic Gustavo Llermaly 将我们的 Jira 内容索引到 Elaasticsearch 中以创建统一的数据源并使用文档级别安全性进行搜索。 在本文中&#xff0c;我们将回顾 Elastic Jira 原生连接器的一个用例。我们将使用一个模拟项目&#xff0c;其中一家银行正在开发…

基于单片机的直流电机控制系统(论文+源码)

1 系统方案设计 本设计基于单片机的直流电机控制系统的总体架构设计如图2.1所示&#xff0c;其采用STM32F103单片机作为控制器&#xff0c;结合ESP8266 WiFi通信模块、L9110电机驱动电路、OLED液晶、按键等构成整个系统。用户在使用时&#xff0c;可以通过按键或者手机APP设定直…

【Java 数据导出到 Word实现方案】使用EasyPOI 工具包进行简易的word操作

文章目录 前言工具包调研实现方案主要步骤&#xff1a;1. 导入 EasyPOI 依赖2. 创建 Word 文件3. 添加数据到 Word 文件4. 保存文件到本地 使用过程中可能遇到的问题总结 前言 最近业务方说周报、月报让他们很头疼&#xff0c;每次都要统计数据后&#xff0c;手动录入到word文…

【全栈开发】----Mysql基本配置与使用

本篇是在已下载Mysql的情况下进行的&#xff0c;若还未下载或未创建Mysql服务&#xff0c;请转到这篇: 2024 年 MySQL 8.0.40 安装配置、Workbench汉化教程最简易&#xff08;保姆级&#xff09;_mysql8.0.40下载安装教程-CSDN博客 本文对于mysql的操作均使用控制台sql原生代码…