数据结构---队列的实现

news2024/12/26 11:56:41

文章目录

  • 前言
  • 一、什么是队列?
  • 二、队列接口的实现
    • 1.队列结构的定义
    • 2.接口实现
  • 总结

前言

队列是一种特殊的线性表。

特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。

进行插入操作的端称为队尾,进行删除操作的端称为队头。

队列中没有元素时,称为空队列。

队列的数据元素又称为队列元素。

在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。

因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表


一、什么是队列?

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。

队列具有先进先出FIFO(First In First Out)

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

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

 

二、队列接口的实现

1.队列结构的定义

//队列--先进先出--用链表实现
typedef int QDataType;

//队列的单节点定义
typedef struct QNode
{
	QDataType val;
	struct QNode* next;
}QNode;

//队列整体定义,有头,尾,以及元素个数
typedef struct Queue
{
	QNode* head;
	QNode* tail;
	int size;
}Queue;

原因:队列使用链表实现,使其每个节点的定义为链表节点形式,而因为队列是一个线性结构,需要有头尾节点进行访问,而且还需要返回其元素个数,便于某些特定场合下的访问,需要将其封装到结构体中,便于访问,因而定义两个结构体形式。

2.接口实现

1. 初始化

//初始化
void QInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
	pq->size = 0;
}

为什么加断言?

可以明确的知道,pq指针不为空,则需要进行断言,避免他人传错参数。

2. 销毁

//销毁
void QDestroy(Queue* pq)
{
	//空队列没必要销毁
	assert(pq);
	assert(pq->head != NULL);
	//依次进行释放
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* after = cur->next;
		free(cur);
		cur = after;
	}
	pq->head = pq->tail = NULL;
	pq->size = 0;
}

因为是从堆上动态开辟出来的节点,需要依次释放,避免一次性释放,无法找到剩下的节点,导致出现内存泄漏。

3. 插入(入队)

//插入--入队列
void QPush(Queue* pq, QDataType x)
{
	assert(pq);

	//开辟一个新的节点
	QNode* newnode = (QNode*)malloc(sizeof(QNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		return;
	}
	newnode->next = NULL;
	newnode->val = x;
	//链接--尾插
	if (pq->head == NULL)
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
	pq->size++;
}

入队过程:1.进行新节点的开辟,需要对malloc的结果进行检查,有备无患

2.有了新节点,需要进行链接过程,链接过程中,需要进行对于队列头尾指针的检查,避免出现非法访问的情况,因为在初始化过程,对于head和tail是赋为空指针的

3.检查完是否为空指针后,即开始链接,也就是进行普通的尾插过程。

4. 删除(出队列)

//删除--出队列
void QPop(Queue* pq)
{
	assert(pq);
	assert(pq->head != NULL);
	//因为队列的性质,先进先出,则其删除是头删
	QNode* after = pq->head->next;
	free(pq->head);
	pq->head = after;
	pq->size--;
}

出队列过程:普通的头删即可,但是,需要注意的是空队列无需删除,需要对head进行判断,否则会出现非法访问情况

5. 获取元素个数

//返回队列元素个数
int QSize(Queue* pq)
{
	assert(pq);
	return pq->size;
}

很普通的操作,但是在某些特定的环境下,可以发挥出神奇的效果,可以使得获取元素效率很快

6. 获取队头和队尾元素及判空

//判空
bool QEmpty(Queue* pq)
{
	assert(pq);
	return pq->size == 0;
}

//取队头元素
QDataType QFront(Queue* pq)
{
	assert(pq);
	//空队列不用取元素
	assert(!QEmpty(pq));
	return pq->head->val;

}

//取队尾元素
QDataType QRear(Queue* pq)
{
	assert(pq);
	//空队列不用取元素
	assert(!QEmpty(pq));
	return pq->tail->val;
}

判空和获取队头队尾元素配合使用,因为空的队列无法获取元素


总结

队列,数据结构中的特殊结构,具有先进先出的特性,使得在某些场合会被频繁利用,所以对于身为学习者的我们,需要掌握其实现逻辑和实现方法。

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

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

相关文章

【Vue.js】1668- 初中级前端必须掌握的 10 个 Vue 优化技巧

优化 Vue.js 应用性能是每个前端开发人员都需要关注的问题。本文我将分享 10 个初中级前端必须掌握的 Vue.js 优化技巧,无论您是正在学习 Vue.js,还是已经在应用开发中使用它,希望这些技巧都会对你的工作有所帮助。 1. 优雅的设置 v-for 中的…

Java 中常见的 Exception 有哪些

Java 是一种广泛使用的编程语言,它的强大和流行程度在很大程度上归功于它的异常处理机制。异常是在程序执行期间出现的错误或意外情况。在 Java 中,异常是通过抛出和捕获异常对象来处理的。在本文中,我们将介绍 Java 中的一些常见异常类型及其…

浅堆深堆解读

浅堆(Shallow Heap) 浅堆是指一个对象所消耗的内存。在32位系统中,一个对象引用会占据4个字节,一个int类型会占据4个字节,long型变量会占据8个字节,每个对象头需要占用8个字节。根据堆快照格式不同&#x…

【STM32】知识补充 深入探讨预分频器

【STM32】知识补充 深入探讨预分频器 概述分频器是什么工作原理计数器预分频器触发器预分频器模数计数器预分频器上升沿和下降沿 应用场景微控制器时钟预分频通信系统中的频率合成计时器与 PWM 波形生成数字电路设计中的同步与计时 预分频器实现方法硬件预分频器软件预分频器 案…

Swift之深入解析如何使用和自定义高级运算符

一、前言 在我之前的博客 Swift之深入解析如何自定义操作符 介绍了“基本运算符”,Swift 还提供了数种可以对数值进行复杂运算的高级运算符,它们包含了在 C 和 Objective-C 中已经被大家所熟知的位运算符和移位运算符。与 C 语言中的算术运算符不同&…

【flask】理解flask的几个难点,难啃的骨头,线程隔离啥的

1.三种路由和各自的比较 2.配置文件所有的字母必须大写 3.if __name__的作用 4.核心对象循环引用的几种解决方式–难 5.Flask的经典错误 6.上下文管理器 7.flask的多线程和线程隔离 三种路由 方法1:装饰器 python C#, java 都可以用这种方式 from flask import F…

SSM整合(三) | 异常处理器 - 项目异常的处理方案

文章目录 异常处理器异常处理器快速入门项目异常处理 异常处理器 异常处理器快速入门 程序开发过程中不可避免的会遇到异常现象 出现异常现象的常见位置与常见原因如下: 框架内部抛出的异常:因使用不规范导致 数据层抛出的异常:因外部服务器…

使用Statsmodel进行假设检验和线性回归

如果你使用 Python 处理数据,你可能听说过 statsmodel 库。Statsmodels 是一个 Python 模块,它提供各种统计模型和函数来探索、分析和可视化数据。该库广泛用于学术研究、金融和数据科学。在本文中,我们将介绍 statsmodel 库的基础知识、如何…

【技巧】Excel序号设置自动更新

做Excel表格的时候,我们经常需要设置序号,在输入序号的时候,你是不是这样做?手动输入序号1,再向下填充,当遇到有不想要的内容,点删除后,发现中间的序号就不连贯了,再手动…

二十五、OSPF高级技术——开销值、虚链路、邻居建立、LSA、多进程

文章目录 调试指令(三张表)1、邻居表:dis ospf peer brief2、拓扑表(链路状态数据库):dis ospf lsdb3、路由表:dis ip routing-table 一、OSPF 开销值/度量值(cost)1、co…

代码审计笔记之开篇

思想 代码审计是从软件测试发展而来,早起一般采用常规软件测试与渗透测试的手段来发现源码漏洞,但是随着软件规模的越来越大,架构越来越复杂,安全漏洞和后门也越来越多越来越隐蔽,这使得传统的软件测试方法很难检出源…

【Java入门合集】第二章Java语言基础(一)

【Java入门合集】第二章Java语言基础(一) 博主:命运之光 专栏JAVA入门 学习目标 掌握变量、常量、表达式的概念,数据类型及变量的定义方法; 掌握常用运算符的使用; 掌握程序的顺序结构、选择结构和循环结构…

C/C++每日一练(20230501)

目录 1. 对链表进行插入排序 🌟🌟 2. 找出小于平均值的数 ※ 3. 二叉树的最大深度 🌟 🌟 每日一练刷题专栏 🌟 Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 对链表进行…

【五一创作】Apollo(入门)

Apollo(入门) Quick Start 配置中心是一种统一管理各种应用配置的基础服务组件 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且…

Springboot 实战一个依赖解决XSS攻击

1. 什么是XSS介绍 XSS: Cross Site Scripting,为不和层叠样式表(Cascading Style Sheets, CSS) 的缩写混淆,故将跨站脚本攻击缩写为XSS。 恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中 Web里面的Scrip…

【高并发】并发数据结构与多核编程

系列综述: 💞目的:本系列是个人整理为了秋招面试的,整理期间苛求每个知识点,平衡理解简易度与深入程度。 🥰来源:材料主要源于多处理器编程的艺术进行的,每个知识点的修正和深入主要…

【JavaEE初阶】认识线程(Thread)

目录 🌾 前言 🌾 了解线程 🌈1.1 线程是什么? 🌈1.2 一些基本问题 🌾2、创建线程的方式 🌈 2.1 继承Thread类 🌈 2.2 实现Runnable接口并重写run()方法 🌈 注意…

有哪些好的学习方法?学霸们自己在用,却不愿意透露的

临近期末,很多家长都在跟我咨询,怎么才能提升孩子的学习效率? 原因就是,每天看着自己的孩子学习到深夜,但不少内容还是记不住, 学习和复习的效果非常的不理想。 今天,给大家分享的方法,是我自己一直也都在用的方法,效果非常的棒。 学长Ron,江苏某省重点高中毕业,高…

给公司搭建一个人才库系统,前台(信息填写+简历上传)后台(筛选功能+下载简历)

首先指出目前代码的不足之处: 如果公司使用,代码还存在风险问题,需要增加防火墙、防PHP攻击、后台加验证等操作 以下指南: 1.Mod Security 和 Fail2Ban 是开源的安全软件,您可以在宝塔面板上安装和配置这些软件来增强您…

【JUC】ThreadLocal

【JUC】ThreadLocal 文章目录 【JUC】ThreadLocal1. 概述2. Thread、ThreadLocal、ThreadLocalMap 关系2.1 Thread 和 ThreadLocal2.2 ThreadLocal 和 ThreadLocalMap2.3 三者之间的关系 1. 概述 ThreadLocal 提供线程局部变量。这些变量与正常的变量不同,因为每一…