数据结构之——队列详解

目录

前言:

一、什么是队列

二、队列的实现

        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。

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

完! 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringSecurity集成第三方登录

SpringSecurity 集成第三方登录 认证及自定义流程 首先我们提供一个实现了AbstractAuthenticationProcessingFilter抽象类的过滤器&#xff0c;用来代替UsernamePasswordAuthenticationFilter逻辑&#xff0c;然后提供一个AuthenticationProvider实现类代替AbstractUserDetail…

vue3vue3vue3vue3vue3vue3vue3vue3vue3vue3vue3vue3

纯vue3的语法 一.创建&#xff08;基于vite&#xff09; 1.在指定目录下运行 npm create vuelatest 项目名称&#xff1a;英文小写下划线数字回车表示确定是、否 左右切换路由、pina、单元测试、端到端的测试、开启eslint控制代码质量 先选择no&#xff0c;学的时候自己手动…

Golang | Leetcode Golang题解之第78题子集

题目&#xff1a; 题解&#xff1a; func subsets(nums []int) (ans [][]int) {set : []int{}var dfs func(int)dfs func(cur int) {if cur len(nums) {ans append(ans, append([]int(nil), set...))return}set append(set, nums[cur])dfs(cur 1)set set[:len(set)-1]df…

Reactor Netty 其他-响应式编程-018

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace The Nex…

triton编译学习

一 流程 Triton-MLIR: 从DSL到PTX - 知乎 (zhihu.com)https://zhuanlan.zhihu.com/p/671434808Superjomns blog | OpenAI/Triton MLIR 迁移工作简介https://superjom

ctfshow SSRF 351-358

做题前,需要先学习关于ssrf漏洞的相关知识 小注意: 当使用 file_get_contents() 函数访问远程 URL 时&#xff0c;它会尝试获取该 URL 指向的资源的内容&#xff0c;并将内容以字符串的形式返回。 如果 b.php 文件是一个 PHP 文件&#xff0c;它包含的内容取决于该 PHP 文件…

【QT学习】补充:qt使用已经存在的类

1.右键项目--》添加现有文件 注意&#xff1a;不是添加新文件&#xff01;&#xff01;&#xff01; 2.添加配置

【Unity Shader入门精要 第6章】基础光照(二)

1. 获取环境光 unity shader中可以通过 UNITY_LIGHTMODEL_AMBIENT获取当前环境光颜色信息。 fixed4 frag(v2f i) : SV_Target {return UNITY_LIGHTMODEL_AMBIENT; }2. 漫反射 2.1 兰伯特模型 创建Chapter_6_Diffuse_Lambert作为测试材质创建Chapter_6_Diffuse_Lambert作为测…

i春秋-GetFlag

题目 考点 sql注入&#xff0c;md5加密&#xff0c;代码审计&#xff0c;利用eval函数 解题 参考wp https://www.cnblogs.com/qiaowukong/p/13630130.html找md5值 看见验证码中的提示&#xff0c;就是去找一个md5值前六位是指定值的数&#xff08;严格来说不一定是数&…

408算法题专项-2019年

题目&#xff1a; 分析&#xff1a;要求空间复杂度为O&#xff08;1&#xff09;&#xff0c;我们可以逆向假设可以开空间&#xff0c;得出一种思路&#xff0c;然后对这种思路优化空间即可得到O&#xff08;1&#xff09; 思路一&#xff1a;假设开空间 思考&#xff1a;再开…

【C语言题解】用函数来模拟实现strlen()、strcpy()、strcmp()、strcat()

&#x1f970;欢迎关注 轻松拿捏C语言系列&#xff0c;来和 小哇 一起进步&#xff01;✊ 学习了函数后&#xff0c;老师让我们用函数来实现上面这四个字符串函数。 我们首先来了解一下这四个字符串函数&#xff1a; 1.strlen函数 用于获取字符串长度&#xff08;不包括末尾…

读天才与算法:人脑与AI的数学思维笔记25_涌现理论

1. 人工智能新闻 1.1. 人工智能新闻报道算法的核心是如何将未经处理的原始数据转换成新闻报道 1.2. 很少有记者为美联社决定使用机器来帮助报道这些新闻持反对意见 1.2.1. 像“Wordsmith”这样的算法&#xff0c;具有自动化的洞察力、科学的叙事能力&#xff0c;现在正被应用…

2024年建筑施工特种作业人员安全生产知识试题

100分题库提供安全员考试试题、建筑安全员考试预测题、建筑安全员ABC考试真题、安全员证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 单选题&#xff08;1-10&#xff09; 1.因生产安全事故受损害的从业人员&#xff0c;除…

打开远程连接的命令是什么?

远程连接是一种能够在不同设备之间建立连接并共享信息的技术。在许多情况下&#xff0c;我们需要通过远程连接来访问其他设备或处理一些远程任务。本文将介绍一些常用的打开远程连接的命令。 使用SSH连接远程设备 SSH&#xff08;Secure Shell&#xff09;是一种安全的网络协议…

大数据Scala教程从入门到精通第六篇:Scala编译结果反编译分析

一&#xff1a;Scala编译结果反编译分析 问题&#xff1a;为什么Scalac之后的生成的class文件有两个&#xff0c;一个带$的&#xff0c;一个不带$的&#xff1f; 不能直接java 执行scala编译的字节码文件。 直接运行的话就会报错&#xff0c;会报一个类没有被找到。 引入类库就…

免费思维13招之六:功能型思维

免费思维13招之六&#xff1a;功能型思维 这节来学习一下免费思维的另一大思维——功能型思维。 这个思维通俗易懂。功能型思维是指将其他产品的功能在我们的产品上进行体现&#xff0c;让客户获得免费的使用。 也就是说&#xff0c;客户买了你的产品&#xff0c;却可以免费得…

Android Studio在android Emulator中运行的项目黑屏

前言&#xff1a; 最近在做一个Android相关的小项目&#xff0c;因为之前这方面的项目做的比较的少。今天在使用虚拟机调试的时候经常出现一些莫名其妙的问题&#xff0c;经过自己多次的尝试和搜索终于解决了这些问题。 问题&#xff1a; 每次run&#xff08;运行&#xff09…

报表-集成

1、部署报表服务器 以centos为例 1.1 将服务拷贝到服务器 其中JDK-17是对应平台的jdk 1.2 修改lite-report下的source.config 1.3 把设计好的报表文件拷贝到lite-report/report 1.4 启动服务&#xff1a;sh run.sh restart 2、使用Nginx location /litereport/ { …

【全面介绍下Spring】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

Golang | Leetcode Golang题解之第77题组合

题目&#xff1a; 题解&#xff1a; func combine(n int, k int) (ans [][]int) {// 初始化// 将 temp 中 [0, k - 1] 每个位置 i 设置为 i 1&#xff0c;即 [0, k - 1] 存 [1, k]// 末尾加一位 n 1 作为哨兵temp : []int{}for i : 1; i < k; i {temp append(temp, i)}t…