初阶数据结构(六)队列的介绍与实现

💓博主csdn个人主页:小小unicorn💓
⏩专栏分类:C++

🚚代码仓库:小小unicorn的学习足迹🚚
🌹🌹🌹关注我带你学习编程知识

  • 队列的介绍
    • 队列的概念:
    • 队列的结构:
  • 队列的实现
    • 创建队列
    • 初始化队列
    • 销毁队列
    • 队尾入队列
    • 对头出队列
    • 获取队列头部元素
    • 获取队列尾部元素
    • 检测队列是否为空
    • 获取队列中有效元素个数
  • 总结:

队列的介绍

队列的概念:

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

入队列:队列的插入操作叫做入队列,进行插入操作的一端称为队尾。

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

队列的结构:

在这里插入图片描述

队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

创建队列

首先我们需要创建一个结点类型,类型包含了该结点的数据指向下一结点的指针。

typedef int QDataType;

typedef struct QListNode
{
	struct QListNode* next;               //指针域
	QDataType data;                       //数据域
}QListNode;

其次队列与普通链表又有所不同,普通链表只需要知道链表的头指针,而队列的信息包括了队头和队尾,所以我们需要再创建一个结构体用于存放队列的队头和队尾。

typedef struct Queue
{
	QListNode* head;//队头
	QListNode* tail;//队尾
}Queue;

初始化队列

我们需要一个初始化函数,对刚创建的队列进行初始化

//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	//起始时队列为空
	pq->head = NULL;
	pq->tail = NULL;
}

销毁队列

因为队列中的每一个结点所占用的内存空间都是动态开辟的,当我们使用完队列后需要及时释放队列中的每一个结点。

//销毁队列
void QueueDestroy(Queue* pq)
{
	assert(pq);

	QListNode* cur = pq->head;//接收队头
	//遍历链表,逐个释放结点
	while (cur)
	{
		QListNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = NULL;//队头置空
	pq->tail = NULL;//队尾置空
}

队尾入队列

入队列,也就是说申请一个新结点并将其链接到队尾,然后改变队尾的指针指向

需要注意的是:若队列中原本无数据,那么我们只需让队头和队尾均指向这个新申请的结点即可。

//队尾入队列
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);

	QListNode* newnode = (QListNode*)malloc(sizeof(QListNode));//申请新结点
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	newnode->data = x;                                        //新结点赋值
	newnode->next = NULL;                                     //新结点指针域置空
	if (pq->head == NULL)                                     //队列中原本无结点
	{
		pq->head = pq->tail = newnode;                         //队头、队尾直接指向新结点
	}
	else                                                       //队列中原本有结点
	{
		pq->tail->next = newnode;                              //最后一个结点指向新结点
		pq->tail = newnode;                                    //改变队尾指针指向
	}
}


对头出队列

出队列,也就是释放队头指针指向的结点并改变队头指针的指向

若队列中只有一个结点,那么直接将该结点释放,然后将队头和队尾置空即可。

//队头出队列
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));                            //检测队列是否为空

	if (pq->head->next == NULL)                         //队列中只有一个结点
	{
		free(pq->head);
		pq->head = NULL;
		pq->tail = NULL;
	}
	else//队列中有多个结点
	{
		QListNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;                                 //改变队头指针指向
	}
}

获取队列头部元素

获取队列头部元素,就是返回队头指针指向的数据。

//获取队列头部元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));                        //检测队列是否为空

	return pq->head->data;                          //返回队头指针指向的数据
}

获取队列尾部元素

获取队列尾部元素,也就是返回队尾指针指向的数据。

//获取队列尾部元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));                  //检测队列是否为空

	return pq->tail->data;                    //返回队尾指针指向的数据
}

检测队列是否为空

检测队列是否为空,也就是判断队头指针指向的内容是否为空。

//检测队列是否为空
bool QueueEmpty(Queue* pq)
{
	assert(pq);

	return pq->head == NULL;
}

获取队列中有效元素个数

队列中有效元素个数,也就是队列中的结点个数

我们只需遍历一下队列,统计队列中的结点数并返回即可。

//获取队列中有效元素个数
int QueueSize(Queue* pq)
{
	assert(pq);

	QListNode* cur = pq->head;                       //接收队头
	int count = 0;                                   //记录结点个数
	while (cur)                                      //遍历队列
	{
		count++;
		cur = cur->next;
	}
	return count;                                    //返回队列中的结点数
}


总结:

初阶数据结构(五)(六)讲的是栈和队列,它们都是特殊的线性表,只不过对插入和删除操作做了限制。

(stack)是限定仅在表尾进行插入和删除操作的线性表。

对列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线
性表。

它们均可以用线性表的顺序存储结构来实现,但都存在着顺序存储的一些弊端。因此它们各自有各自的技巧来解决这个问题。

对于栈来说,如果是两个相同数据类型的栈,则可以用数组的两端作栈底的方法来让两个栈共享数据,这就可以最大化地利用数组的空间。

对于队列来说,为了避免数组插入和删除时需要移动数据,于是就引入了循环队列,使得队头和队尾可以在数组中循环变化。解决了移动数据的时间损耗,使得本来插入和删除是O(n)的时间复杂度变成了O(1)。

它们也都可以通过链式存储结构来实现,实现原则上与线性表基本相同,如下图所示。

文章到这里就要告一段落了,有更好的思路或问题的,欢迎留言评论区。

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

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

相关文章

C++设计模式_02_面向对象设计原则

文章目录 1. 面向对象设计,为什么?2. 重新认识面向对象3. 面向对象设计原则3.1 依赖倒置原则(DIP)3.2 开放封闭原则(OCP )3.3 单一职责原则( SRP )3.4 Liskov 替换原则 ( LSP )3.5 接口隔离原则 ( ISP )3.6 优先使用对象组合,而不是类继承3.7…

【算法日志】动态规划刷题:股票买卖问题(day41)

代码随想录刷题60Day 目录 前言 买卖股票的最佳时机1 买卖股票的最佳时机2 买卖股票的最佳时机3 买卖股票的最佳时机4 前言 本日着重于多状态问题的处理,各状态之间会有一定联系,状态转移方程将不再局限一个。 买卖股票的最佳时机1 int maxProfit(…

RHCE——九、SELinux

SELinux 一、概念1、作用2、SELinux与传统的权限区别 二、SELinux工作原理1、名词解释主体(Subject)目标(Object)策略(Policy)安全上下文(Security Context) 2、文件安全上下文查看1…

[ZenTao]源码阅读:自定义任务类型

1、module/custom/control.php 2、module/custom/model.php

php开发环境搭建_宝塔、composer

宝塔面板下载,免费全能的服务器运维软件 一 下载宝塔面板 解压安装 登录之后修改安全入口 1 进入软件商店下载nginx,mysql5.6,php7.2 2 将php的安装路径配置到环境变量中 此电脑--右键--点击属性---高级系统设置---环境变量---系统变量path---添加确定 输入php -v…

音视频技术开发周刊 | 308

每周一期,纵览音视频技术领域的干货。 新闻投稿:contributelivevideostack.com。 OpenAI首席科学家最新访谈:对模型创业两点建议、安全与对齐、Transformer够好吗? OpenAI首席科学家Ilya Sutskever最近和他的朋友Sven Strohband进…

大数据到底是好是坏?_光点科技

近年来,随着科技的不断发展和互联网的普及,大数据已经成为一个备受关注的话题。它带来了许多机遇和挑战,引发了人们对于其是好是坏的争议。大数据究竟是一把双刃剑,需要我们从多个角度来审视。 大数据的好处无疑是显而易见的。首先…

java入坑之网络编程

一、 网络基础知识 1.1网卡 1.2IP地址 1.3端口 1.4保留IP 1.5网络协议 二、UDP 编程 2.1相关概念 计算机通讯:数据从一个IP的port出发(发送方),运输到另外一个IP的port(接收方) UDP:无连接无…

详解I2C

I2C(也常写作 I I C IIC IIC, I 2 C I^2C I2C),全称为Inter-Integrated Circuit(“互连集成电路”),用于在集成电路之间进行短距离数据传输。它由Philips(现在的NXP半导体&#xff0…

DolphinDB 携手白鲸开源 WhaleStudio 打造高效敏捷的 DataOps 解决方案

浙江智臾科技有限公司(简称:DolphinDB)和北京白鲸开源科技有限公司(简称:白鲸开源)是在大数据技术领域活跃的两支专业团队。 DolphinDB 专注于为用户提供集高性能存储、复杂分析能力和流处理于一体的实时计…

Linux内核源码分析 (5)多处理器调度

Linux内核源码分析 (5)多处理器调度 文章目录 Linux内核源码分析 (5)多处理器调度注:本章节使用的内核版本为Linux 5.6.18一、 SMT和NUMA1、SMP (对称多处理器结构)2、NUMA (非一致内存访问结构) 二、多核调度三、调度域和调度组四、SMP调度详…

Power BI 连接 MySQL 数据库

Power Query 或 Power BI 只提供了对 SQL Server 的直接连接,而不支持其它数据库的直连。所以第一次连接 MySQL 数据库时,就出现下面的错误信。 这就需要我们自己去安装一个连接器组件。https://downloads.mysql.com/archives/c-net/ 错误解决方案 我一…

MySQL 8 数据清洗总结

MySQL 8 数据清洗三要素: 库表拷贝和数据备份数据清洗SQL数据清洗必杀技-存储过程 前提:数据库关联库表初始化和基础数据初始化: -- usc.t_project definitionCREATE TABLE t_project (id varchar(64) NOT NULL COMMENT 主键,tid varchar(…

Spring MVC 五 - Spring MVC的配置和DispatcherServlet初始化过程

今天的内容是SpringMVC的初始化过程,其实也就是DispatcherServilet的初始化过程。 Special Bean Types DispatcherServlet委托如下一些特殊的bean来处理请求、并渲染正确的返回。这些特殊的bean是Spring MVC框架管理的bean、按照Spring框架的约定处理相关请求&…

rtsp 拉流 gb28181 收流 经AI 算法 再生成 rtsp server (一)

1、 rtsp 工具 1 vlc 必备工具 2 wireshark 必备工具 3 自己制作的工具 player 使用tcp 拉流,不自己写的话,使用ffmpeg 去写一个播放器就行 4 live555 编译好live555, 将live555的参数修改以下,主要是缓存大小 文章使用c 来写一…

JavaScript Web APIs-01学习

复习: splice() 方法用于添加或删除数组中的元素。 **注意:**这种方法会改变原始数组。 删除数组: splice(起始位置, 删除的个数) 比如:1 let arr [red, green, blue] arr.splice(1,1) // 删除green元素 consol…

LinkedHashMap实现LRU缓存cache机制,Kotlin

LinkedHashMap实现LRU缓存cache机制,Kotlin LinkedHashMap的accessOrdertrue后,访问LinkedHashMap里面存储的元素,LinkedHashMap就会把该元素移动到最尾部。利用这一点,可以设置一个缓存的上限值,当存入的缓存数理超过…

取一个整数各偶数位上的数构成一个新的数字

1 题目 我可太难了,这题我的思路有点复杂,遇到的困难很多,总是值传递搞不清楚,地址传递总是写错。 从低位开始取出一个整数s的各奇数位上的数,剩下的偶数位的数依次构成一个新数t。 例如: 输入s&#xff…

vue自定义键盘

<template><div class"mark" click"isOver"></div><div class"mycar"><div class"mycar_list"><div class"mycar_list_con"><p class"mycar_list_p">车牌号</p>…

浪潮云海护航省联社金融上云,“一云多芯”赋能数字农业

农村金融是现代金融体系的重要组成部分&#xff0c;是农业农村发展的重要支撑力量&#xff0c;而统管全省农商行及农信社的省级农村信用社联合社&#xff08;以下简称&#xff1a;省联社&#xff09;在我国金融系统中占据着举足轻重的地位。省联社通常采用“大平台小法人”的发…