数据结构之——队列详解

目录

前言:

一、什么是队列

二、队列的实现

        2.1 队列结构

        2.2 队列初始化

        2.3 队列销毁

        2.4 入队列

        2.5 出队列

        2.6 获取队列头部元素 

        2.7  获取队列尾部元素 

        2.8 获取队列中有效元素个数 

        2.9 检测队列是否为空

三、 代码总览

        Queue.h

        test.c

四、例题


前言:

        我们前面已经学习了栈,今天我们来学习队列,队列和栈一样,相对来说比较简单,随后,会为大家准备OJ练习题,敬请期待!

一、什么是队列

        队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)

        入队列:进行插入操作的一端称为队尾

        出队列:进行删除操作的一 端称为队头

        这里简单给大家解释一下:

        大家肯定都排过队(别说没有,我不信),大家在排好队先前前进时,是不是先站到队伍里的先走。队列的原理何其类似。因为,你可以猜一猜它为什么叫队列。可用下面图片帮助大家理解。 

         明白了,基础知识,那就一起来实现一下队列吧。

二、队列的实现

        2.1 队列结构

                和栈一样,我们队列的结构该如何设计呢?

                队列一共有两种结构,分为:顺序结构链式结构

  • 队列的顺序结构

入队,不需要移动任何元素,时间复杂度为O(1)

出队,所有元素需要往前移动,时间复杂度为O(N)

  • 队列的链式结构

首先我们定义两个指针,队头指针指向第一个节点,队尾指针指向尾节点

入队(尾插),时间复杂度为O(1)

出队(头删),时间复杂度为O(1)

 

                这里,我们将采取链式结构,如若对顺序结构感兴趣可结合之前的栈进行实现。

                我们要采用链式难道要用二级指针吗?一级已经够麻烦了,使用二级会更晕。所以,为了避免这种轻快,我们可采取结构体,如下代码:

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

                这样即可避免二级指针。

        2.2 队列初始化

// 初始化队列 
void QueueInit(Queue* q)
{assert(q);q->phead = q->ptatil = NULL;q->size = 0;
}

                初始化只用将头和尾置为空即可。队列还未建立,所以,先不管。

        2.3 队列销毁

// 销毁队列 
void QueueDestroy(Queue* q)
{assert(q);QNode* cur = q->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}q->phead = q->ptatil = NULL;q->size = 0;
}

                销毁时我们要释放的是指针所指向开辟空间,而不是指针本身。所以,使用一个while循来释放。

        2.4 入队列

// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{assert(q);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->next = NULL;newnode->data = data;if (q->phead == NULL)//这里使用头节点,尾节点判断均可{q->phead = q->ptatil = newnode;}else{q->ptatil->next = newnode;//记住这里是尾节点,不是头节点!!!q->ptatil = newnode;}q->size++;
}

                入队列时,我们要为其开辟一块空间也就是QNode,这就是队列的元素。要分为两种情况讨论,队列为空和队列不为空。

        2.5 出队列

// 队头出队列 
void QueuePop(Queue* q)
{assert(q);assert(q->size != 0);if (q->phead->next == NULL){q->phead = q->ptatil = NULL;}else{QNode* next = q->phead->next;free(q->phead);q->phead = next;}q->size--;
}

                要注意:分两种情况进行讨论。

        2.6 获取队列头部元素 

// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{assert(q);assert(q->phead);return q->phead->data;
}

                这里,直接用头指针返回值即可。

        2.7  获取队列尾部元素 

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

                和上面一样,运用指针获取值即可。

        2.8 获取队列中有效元素个数 

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

        2.9 检测队列是否为空

// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* q)
{assert(q);return q->size == 0;
}

三、 代码总览

        Queue.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int QDataType;
// 链式结构:表示队列
typedef struct QListNode
{struct QListNode* next;QDataType data;
}QNode;// 队列的结构 
typedef struct Queue
{QNode* phead;QNode* ptatil;int size;
}Queue;// 初始化队列 
void QueueInit(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDataType data);
// 队头出队列 
void QueuePop(Queue* q);
// 获取队列头部元素 
QDataType QueueFront(Queue* q);
// 获取队列队尾元素 
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);

        Queue.c

#include"Queue.h"// 初始化队列 
void QueueInit(Queue* q)
{assert(q);q->phead = q->ptatil = NULL;q->size = 0;
}
// 队尾入队列 
void QueuePush(Queue* q, QDataType data)
{assert(q);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->next = NULL;newnode->data = data;if (q->phead == NULL){q->phead = q->ptatil = newnode;}else{q->ptatil->next = newnode;//记住这里是尾节点,不是头节点!!!q->ptatil = newnode;}q->size++;
}
// 队头出队列 
void QueuePop(Queue* q)
{assert(q);assert(q->size != 0);if (q->phead->next == NULL){q->phead = q->ptatil = NULL;}else{QNode* next = q->phead->next;free(q->phead);q->phead = next;}q->size--;
}
// 获取队列头部元素 
QDataType QueueFront(Queue* q)
{assert(q);assert(q->phead);return q->phead->data;
}
// 获取队列队尾元素 
QDataType QueueBack(Queue* q)
{assert(q);assert(q->ptatil);return q->ptatil->data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q)
{assert(q);return q->size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* q)
{assert(q);return q->size == 0;
}
// 销毁队列 
void QueueDestroy(Queue* q)
{assert(q);QNode* cur = q->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}q->phead = q->ptatil = NULL;q->size = 0;
}

        test.c

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

四、例题

        来一道例题来练一练吧!

        现有队列Q与栈S,初始时Q中的元素依次是 1,2,3,4,5,6(1在队头),S 为空。若仅允许下列3种操作:①出队并输出出队元素;②出队并将出队元素入栈;③出栈并输出出栈元素,则不能得到的输出序列是()。

                       A. 1,2,5,6,4,3                                        B.  2,3,4,5,6,1                                        C. 3,4,5,6,1,2                                         D.  6.5.4.3.2.1

        

        可得:答案为:C。

        如果还有什么问题,可以私信也可在评论区留言!

完! 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/10505.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

树莓派、ubuntu低版本python3安装库

如果遇到树莓派中自带低版本python3&#xff0c;又不想额外去安装python3时&#xff0c;可能会遇到版本过低&#xff0c;无法安装库的情况&#xff0c;以下用我实际情况举例解决方案。 本次遇到的问题是树莓派低版本中&#xff0c;python3为3.7.3&#xff0c;需要安装numpy&am…

Python专题:八、列表(1)

Python的内置数据类型 数据类型&#xff1a;列表 list类型 可以是字符串&#xff0c;浮点数&#xff0c;整数&#xff0c;列表 列表特性 ①集合性的数据类型 ②列表是有序的 ③列表是可更新的 访问列表元素的方式也是[索引]&#xff0c;也是从0开始的&#xff0c;不能超过…

EasyNmon服务器性能监控工具环境搭建

一、安装jdk环境 1、看我这篇博客 https://blog.csdn.net/weixin_54542209/article/details/138704468 二、下载最新easyNmon包 1、下载地址 https://github.com/mzky/easyNmon/releases wget https://github.com/mzky/easyNmon/releases/download/v1.9/easyNmon_AMD64.tar.…

GitLab CI/CD的原理及应用详解(一)

本系列文章简介&#xff1a; 在当今快速变化的软件开发环境中&#xff0c;持续集成&#xff08;Continuous Integration, CI&#xff09;和持续交付&#xff08;Continuous Delivery, CD&#xff09;已经成为提高软件开发效率、确保代码质量以及快速响应市场需求的重要手段。Gi…

Ansible-inventory和playbook

文章目录 一、inventory 主机清单1、列表表示2、inventory 中的变量3、变量3.1 主机变量3.2 组变量3.3 组嵌套 二、playbook剧本1、playbook的组成2、编写剧本2.1 剧本制作2.2 准备nginx.conf2.3 运行剧本2.4 查看webservers服务器2.5 补充参数 3、剧本定义、引用变量3.1 剧本制…

要将D-SUB电缆连接到工装接口和被测件接口

准备工作&#xff1a; • 确认D-SUB电缆的类型&#xff08;如DB9、DB25等&#xff09;与工装接口和被测件接口匹配。 • 检查电缆两端的接口是否完好无损&#xff0c;无弯曲针脚或损坏的屏蔽层。 • 确保工作区域整洁&#xff0c;避免灰尘或异物进入接口。 • 识别接口&…

河源知识付费系统报价,教育机构怎么进行网络推广呢?

中国教育培训领域的市场空间巨大。教育支出在中国已经超过其他生活费用成为仅次于食物的第二大日常支出。做好线上的营销推广成为了各大企业主思索的问题。其实对于教育行业的网络营销推广方式有很多种&#xff0c;其中大部分与其他行业的形式相同。教育机构怎么进行网络推广呢…

kdb 调试内核-延迟驱动加载

说明: 系统在启动过程中&#xff0c;一些要调试的驱动在 "进入kdb 之前" 就已经加载了&#xff0c; 那么&#xff0c;我们就需要延迟 "加载驱动" #define XX_module_platform_driver(__platform_driver) \XX_module_driver(__platform_driver, platform_d…

【Java】高效解决 非降序数组合并 两种方法

欢迎浏览高耳机的博客 希望我们彼此都有更好的收获 感谢三连支持&#xff01; oj&#xff1a;https://leetcode.cn/problems/merge-sorted-array/submissions/ 合并两个有序数组是个经典问题&#xff0c;它不仅在算法学习中频繁出现&#xff0c;也在实际开发中经常遇到。合并数…

计算机毕业设计】springbootBBS论坛系统

本系统为用户而设计制作 BBS论坛系统&#xff0c;旨在实现BBS论坛智能化、现代化管理。本BBS论坛自动化系统的开发和研制的最终目的是将BBS论坛的运作模式从手工记录数据转变为网络信息查询管理&#xff0c;从而为现代管理人员的使用提供更多的便利和条件。使BBS论坛系统数字化…

ADS基础介绍篇1

一. ADS简介 常用的射频仿真软件有ADS和AWR&#xff0c;ADS(Advanced Design system)最传统&#xff0c;是Agilent公司于2008年推出的电磁场仿真器&#xff0c;可提供原理图设计和layout版图设计。仿真功能十分强大&#xff0c;可提供从无源到有源&#xff0c;从直流到交流&am…

(十一)JSP教程——page对象

page对象用来处理当前请求的JSP页面的实现类的实例&#xff0c;相当于Java类中的this&#xff0c;这个对象在JSP中应用并不是很多。 page对象提供的主要方法及其说明。 getClass&#xff08;&#xff09;获得对象运行时的类 hashCode ()获得该对象的哈希码值 …

关于 MongoDB 数据库基本操作的详细介绍

MongoDB 是一个基于分布式文件存储的数据库&#xff0c;其设计旨在提供高性能、可扩展性和易用性。以下是关于 MongoDB 数据库基本操作的详细介绍 一、MongoDB 简介 MongoDB 是一个面向文档的数据库&#xff0c;其数据存储在类似 JSON 的 BSON&#xff08;Binary JSON&#x…

在Chisel3中,不支持对子字(subword)进行赋值。在 Chisel 中,UInt 类型是一个不可变的位宽数据类型,它表示一个固定位宽的无符号整数。

在Chisel3中&#xff0c;不支持对子字&#xff08;subword&#xff09;进行赋值。这种设计决策背后的原因涉及到硬件描述语言中类型和数据抽象的最佳实践。 不支持子字赋值的原因 硬件描述的性质&#xff1a; 在硬件设计中&#xff0c;操作和修改单独的位或子字通常与较高的复…

Docker搭建ctfd平台

安装docker和docker-compose &#xff08;1&#xff09;安装docker&#xff1a; curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun&#xff08;2&#xff09;安装 Docker Compose&#xff1a; yum install docker-compose安装失败参考下面文章 https:/…

stm32——OLED篇

技术笔记&#xff01; 一、OLED显示屏介绍&#xff08;了解&#xff09; 1. OLED显示屏简介 二、OLED驱动原理&#xff08;熟悉&#xff09; 1. 驱动OLED驱动芯片的步骤 2. SSD1306工作时序 三、OLED驱动芯片简介&#xff08;掌握&#xff09; 1. 常用SSD1306指令 2. …

初识sql注入--手工注入

目录 可能使用的sql函数 入侵网站方式 1、文件上传漏洞 2、rce 3、sql注入 SQL注入 什么是sql注入 进行SQL注入 实验环境 开始实验&#xff08;使用information_shema数据库&#xff09; 1、进入靶场 2、报列数 下面来解释一下为什么要照上面SQL语句写 url编码 单…

模拟无线音频传输实验

zkhengyang进数字音频系统研究开发交流答疑群(课题组) 一个单管调频无线话筒模块一台调频收音机&#xff0c;全部自己动手制作调试&#xff0c;无线话筒模块可以接话筒mic&#xff0c;人讲话&#xff0c;收音机接受到语音信号&#xff0c; 或者直接输入模拟音频音乐信号&#…

Linux 文件目录详解

在Linux中一切皆文件&#xff0c;即使是媒体设备在Linux中存储的也是一个文件 目录 1.基本介绍 2. 具体的目录结构 1.基本介绍 Linux的文件系统是采用级层式的树状目录结构&#xff0c;在此结构中的最上层是根目录"/"&#xff0c;然后再此目录下在创建其他的目录&…

使用SPI驱动串行LCD的驱动实现(STM32F4)

目录 概述 1. 硬件介绍 1.1 ST7796-LCD 1.2 MCU IO与LCD PIN对应关系 2 功能实现 2.1 使用STM32Cube配置Project 2.2 STM32Cube生成工程 3 代码实现 3.1 SPI接口实现 3.2 LCD驱动程序实现 3.3 测试程序实现 4 测试 源代码下载地址&#xff1a; https://gitee.com/mf…