【数据结构】—— 队列
- 1、队列的概念
- 2、队列的结构
- 如何选择合适的数据结构实现队列(数组or链表)
- 3、队列的链式存储
- 3.1 队列的链式存储结构
- 3.2 队列的常见接口
- 3.3 队列的接口实现
- 初始化
- 判空
- 入队列
- 出队列
- 获取队头元素
- 获取队尾元素
- 获取节点个数
- 销毁
- 3.4 源代码
- 4、队列的顺序存储(循环队列)
1、队列的概念
队列是一种先进先出(First In First Out ,FIFO)的数据结构,可以简单理解为排队的概念。在队列中,数据项按照插入的顺序排列,并且只能在队列的一端插入(称为队尾),在另一端删除(称为队头)。
2、队列的结构
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头

如何选择合适的数据结构实现队列(数组or链表)
在前面学习的顺序表中,我们知道数组只有在尾插和尾删效率高为O(1),当需要对头部元素操作时效率较低为O(n)。队列的特点是在队尾插入元素,在队头删除元素,序列两端都需要访问,这就导致使用数组实现队列时必定有一端的插入(or删除)效率低,因此不建议使用数组实现队列。
3、队列的链式存储
通过上面的分析,我选择链式存储结构来实现队列。这是因为链式存储结构实现两端的高效访问很简单——只需要增加一个尾指针即可实现两端的O(1)访问
3.1 队列的链式存储结构
定义两个结构体
- QNode:保存队列中节点的元素数据和下一个节点
- Queue:保存头指针、尾指针和队列中有效元素个数
typedef int QDateType;
typedef struct QueueNode
{QDateType val;//当前节点的数据struct QueueNode* next;//当前节点的下一个节点
}QNode;typedef struct Queue
{QNode* phead;//头指针QNode* ptail;//尾指针int size;//记录队列有效元素个数
}Queue;
3.2 队列的常见接口
//初始化
void QueueInit(Queue* pq);
//销毁
void QueueDestroy(Queue* pq);//入队列
void QueuePush(Queue* pq,QDateType x);//出队列
void QueuePop(Queue* pq);
//获取队头元素
QDateType QueueFront(Queue* pq);
//获取队尾元素
QDateType QueueBack(Queue* pq);
//判空
bool QueueEmpty(Queue* pq);
//获取有效元素个数
int QueueSize(Queue* pq);
3.3 队列的接口实现
初始化
头尾指针置空,队列有效元素个数初始化为0
void QueueInit(Queue* pq)
{assert(pq);//哨兵位可选可不选(可以有也可以没有)pq->phead = pq->ptail = NULL;pq->size = 0;
}
判空
直接返回Queue结构体保存的size即可
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}
入队列
队尾入队步骤
(1)申请新节点并初始化该节点(将x赋值,下一个节点置空)
(2)判断是否存在尾节点(队列是否为空)
- 存在尾节点(队列不为空):只需将新节点接到队尾,尾指针后移一位即可。
- 不存在尾节点(队列为空):改变队头和队尾的值即可
(3)队列有效节点个数加1
void QueuePush(Queue* pq, QDateType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));//申请新节点if (newnode == NULL){perror("malloc fail");return;}//对新节点初始化newnode->val = x;newnode->next = NULL;//有尾节点(队列不为空)if (pq->ptail){pq->ptail->next = newnode;pq->ptail = newnode;}else{//一个有效节点都没(队列为空)pq->phead = pq->ptail = newnode;}pq->size++;
}
出队列
(1)判空(队列不为空才能出队)
(2)判断队列有效节点的个数
- 一个节点:释放该节点,将头尾指针置空
- 多个节点:定义临时QNode类型变量保存头节点的下一个节点,释放头节点,头节点更新为保存的节点
(3)队列有效节点个数减1
void QueuePop(Queue* pq)
{assert(pq);//三种情况:0个节点,1个节点,多个节点//0个assert(pq->phead);//暴力检查//if (pq->phead == NULL) return;//温柔检查//队列只有1个有效节点if (pq->phead->next==NULL){free(pq->phead);pq->phead = pq->ptail = NULL;}else{//队列有多个有效节点QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}
获取队头元素
断言判断是否存在头节点,如果存在直接返回头节点的值即可
QDateType QueueFront(Queue* pq)
{assert(pq);//这里只能暴力检查assert(pq->phead);return pq->phead->val;
}
获取队尾元素
断言判断是否存在尾节点,如果存在直接返回尾节点的值即可
QDateType QueueBack(Queue* pq)
{assert(pq);//这里只能暴力检查assert(pq->ptail);return pq->ptail->val;
}
获取节点个数
返回size即可
int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}
销毁
遍历删除(释放)所有节点,最后头尾指针悬空,size置0
void QueueDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}
3.4 源代码
.h文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int QDateType;typedef struct QueueNode
{QDateType val;struct QueueNode* next;
}QNode;
入队
为什么需要两个指针
//void QueuePush(QNode** head,QNode** ptail);
//
出队
//void QueuePop(QNode** head);typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;//初始化
void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);//入队列
void QueuePush(Queue* pq,QDateType x);//出队列
void QueuePop(Queue* pq);QDateType QueueFront(Queue* pq);
QDateType QueueBack(Queue* pq);
bool QueueEmpty(Queue* pq);
int QueueSize(Queue* pq);
.c文件
#include "Queue.h"//初始化
void QueueInit(Queue* pq)
{assert(pq);//哨兵位可选可不选pq->phead = pq->ptail = NULL;pq->size = 0;
}
//销毁
void QueueDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}//入队列
void QueuePush(Queue* pq, QDateType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->val = x;newnode->next = NULL;//有尾节点if (pq->ptail){pq->ptail->next = newnode;pq->ptail = newnode;}else{//一个有效节点都没pq->phead = pq->ptail = newnode;}pq->size++;
}//出队列
void QueuePop(Queue* pq)
{assert(pq);//三种情况:0个节点,1个节点,多个节点//0个assert(pq->phead);//暴力检查//if (pq->phead == NULL) return;//温柔检查//1个if (pq->phead->next==NULL){free(pq->phead);pq->phead = pq->ptail = NULL;}else//多个{QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}QDateType QueueFront(Queue* pq)
{assert(pq);//这里只能暴力检查assert(pq->phead);return pq->phead->val;
}
QDateType QueueBack(Queue* pq)
{assert(pq);//这里只能暴力检查assert(pq->ptail);return pq->ptail->val;
}
bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}
int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}
4、队列的顺序存储(循环队列)
虽然队列的一般实现使用链式存储,但是也有一些情况可以使用数组存储,比如循环队列。
具体可以查看这篇博客———循环队列OJ
END
相关文章:
【数据结构】—— 队列
1、队列的概念2、队列的结构如何选择合适的数据结构实现队列(数组or链表) 3、队列的链式存储3.1 队列的链式存储结构3.2 队列的常见接口3.3 队列的接口实现初始化判空入队列出队列获取队头元素获取队尾元素获取节点个数销毁 3.4 源代码 4、队列的顺序存储…...
vue中openlayers过滤高亮显示某个图层
vue中openlayers过滤高亮显示某个图层 openlayers库没有直接支持这样设置,所以可以使用库:ol-ext,地址:https://viglino.github.io/ol-ext/examples/filter/map.filter.crop.html 效果: 关键代码: /**…...
WPF篇(11)-ToolTip控件(提示工具)+Popup弹出窗口
ToolTip控件 ToolTip控件继承于ContentControl,它不能有逻辑或视觉父级,意思是说它不能以控件的形式实例化,它必须依附于某个控件。因为它的功能被设计成提示信息,当鼠标移动到某个控件上方时,悬停一会儿,…...
【mysql 第一篇章】系统和数据库的交互方法
一、宏观的查看系统怎么和数据库交互 在我们刚刚接触系统和数据库的时候不明白其中的原理,只知道系统和数据库是需要交互的。所以我们会理解成上图的形式。 二、MYSQL 驱动 随着我们的学习时间的加长以及对程序的了解,发现链接数据库是需要有别的工具辅…...
数据结构-位运算总结
位运算总结: 1.求位1的个数 191. 位1的个数 - 力扣(LeetCode) 有两种写法: 1.是把该数不断的去与0x1相与,得到该数的最后一位的值,然后判断他是不是1,再把该数更新一下整体往后移动一位也就…...
java 异常堆栈的由来
编写的程序代码内部错误产生的异常,如调用对象为空(空指针异常)、数组越界异常、除0异常等。这种通常称为未检查的异常(Runtime异常子类),在虚拟机中执行时会集中处理这些异常。其他运行中异常,通过throw语句主动抛出的…...
【推荐系统】【多任务学习】Progressive Layered Extraction (PLE)
Progressive Layered Extraction (PLE): A Novel Multi-Task Learning (MTL) Model for Personalized Recommendations 文章目录 Progressive Layered Extraction (PLE): A Novel Multi-Task Learning (MTL) Model for Personalized Recommendations1 论文出处2 背景2.1 背景介…...
java -转win32/win64免安装jre环境运行
由于java 转为exe,只能在装有JDK环境的电脑运行, 发给其他人也不能运行,缺少环境,程序自己背着jre走 1.先打好jar 包 2.使用exe4j 把jar包转成exe 运行程序 3.使用inno stup ,把exe运行程序加上jre环境 以下是具体实现…...
算法板子:容斥原理——求出 1∼n 中能被质数 p1,p2,…,pm 中的至少一个数整除的整数有多少个
1. 题目要点 1. 设:求1~10中能被质数2和3中至少一个数整除的数有多少个。1~10中能被质数2整除的数的集合记为S1{2,4,6,8,10},能被质数3整除的数的集合记为S2{3,6,9},能同时被质数2和3整数的数的集合为S1∩S2{6} 2. 这道题的目的是求S1∪S2∪S…...
用gurobipy求解带不等式约束条件的优化问题
1. 引入 在当今的数据驱动世界中,优化问题无处不在,从工程设计到经济模型,再到机器学习算法的调参,优化都是实现效率最大化、成本最小化或性能最优化的关键工具。 这里有一个典型的数学优化问题,目标是在给定的约束条…...
漏洞复现-Adobe ColdFusion 远程代码执行漏洞(CVE-2023-38203)
1.漏洞描述 Adobe ColdFusion是一种服务器端的Web应用开发平台。它由Adobe Systems开发,用于创建动态的、交互式的Web应用程序和网站。 Adobe ColdFusion在2018u17及之前版本、2021u7及之前版本和2023u1及之前版本中存在任意代码执行漏洞。该漏洞是由于反序列化不…...
Spring-MyBatis整合:No qualifying bean of type ‘XXX‘ available: ...
1.看一下核心配置中有没有导入myBatis配置 2.看一下service和dao有没有相应注解 3.看一下MyBatisConfig中有没有对sqlSessionFactory和mapperScannerConfigurer注释成bean对象以及有没有配置映射文件路径...
gitea docker 快捷安装部署
前言 在前一篇博文(什么是 Gitea?)中,我们详细介绍了gitea的功能特性,以及其与其它git服务器之间的特性多维度对比。 在本文中,我们将详细介绍gitea的快捷安装部署,docker方式! 1…...
CLAMP-1
一、信息收集 1、主机发现 nmap 192.168.236.0/24 2、端口扫描 nmap 192.168.236.173 -p- -A 3、目录扫描 dirb http://192.168.236.173 二、漏洞探测 访问80端口 访问 /nt4stopc/ 下面有一些问题,提示必须收集答案 都是一些判断题,对与错对应1与0&…...
Blender的Python编程介绍
在Blender这个免费的开源3D设计软件中,最值得称道的一点是可以用Python程序来辅助进行3D设计,我们可以通过Python来调整物体的属性,生成新的物体,甚至生成新的动画等等。 在最近的一个项目中,我用Blender制作了一个动…...
树莓派4/5:运行Yolov5n模型(文末附镜像文件)
〇、前言 因国内网络问题,可直接烧录文末镜像文件,或者按照本教程进行手动操作。 一、实验目的 在树莓派4B运行Yolov5n模型。 二、实验条件 1、Windows 11计算机:安装了Mobaxterm 2、树莓派4B:64Bit Lite OS,安装了…...
【学习笔记】Day 9
一、进度概述 1、inversionnet_train 试运行——成功 二、详情 1、inversionnet_train 试运行 在经历了昨天的事故后,今天最终成功运行了 inversionnet_train,运行结果如下: 经观察,最开始 loss 值大概为 0.5 左右 随着训练量的增…...
Linux网络案例
网络配置基础 WIN10上安装虚拟机,虚拟机里安装CENTOS6.5。 1)网络配置的步骤 (1)CENTOS6.5C网络设置: su root //切换root用户 cd /etc/sysconfig/network-scripts //进入网卡配置文件所在目录 vi ifcfg-eth0 //修改网卡配置文件 …...
苹果离线打包机配置和打包
1、虚拟机安装 macOS虚拟机安装全过程(VMware)-腾讯云开发者社区-腾讯云 给 windows 虚拟机装个 mac 雪之梦 1、安装苹果镜像 去网上下载,打包机的镜像要和自己mac电脑上的保持一致。 同时打包机的用户名也需要和自己的mac保持一致。 2、…...
【C++ Primer Plus】学习笔记 5【指针 下】
文章目录 前言一、指针1.使用new创建动态结构例子:使用new和delete 2.自动存储、静态存储和动态存储1.自动存储2.静态存储3.动态存储 总结 前言 依旧是指针部分ヾ(◍∇◍)ノ゙ 一、指针 1.使用new创建动态结构 将new用于结构由两步组成:创建…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
初学 pytest 记录
安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
