数据结构--队列
一、队列是什么
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。
总结起来两点:
- 一种线性表
- 添加操作只能在表尾,删除操作在表头(先进先出)
二、实现队列的思路
1.初始化一个空队列
初始化一个大小固定的数组,并将头指针,尾指针都指向下表为0的位置,但其实这种初始化头指针指向的是队首,尾指针指向的是队尾的后一个元素。

2.往队列里添加元素
往队列里添加元素,尾指针后移一位。

一直添加直到队列满

这个时候尾指针已经出现在数组下标外了
3.消费队列元素
每消费一个队列元素,头指针指向的元素出队,并且后移一位

再消费两个

这个时候我们想往队列里继续添加元素,尾指针后移,然后发现出现了假溢出的情况,因为尾指针无法再向后移动,而队列实际上并没有满,我们又无法继续往队列里添加数据。这个时候其实有两种解决方案。
方案一:我们每消费一个元素,其后面的元素都整体往前移动一位,就像我们生活中排队打饭一样,后面的人都往前挪一挪。但这种方案带来的后果是,带来的时间开销太大,因为基本上要操作所有的元素,所以这种方案不可行。
方案二:尾指针在指向下表为最后一个元素时,再添加元素,如果还有空位,就将尾指针重新指向0,头指针在取到下表数组末尾时,如果前面还有元素,头指针也指向0,这就是我们说的环形队列。
三、实现环形队列
1.环形队列示例图
尾指针重新指向零

再添加一个元素

连续消费三个元素,如果前面还有元素,头指针也指向0

这个时候我们发现那个原来熟悉的队列又回来了。
Acwing 829 模拟队列
理解和感悟
用数组模拟队列,比用数组模拟栈要麻烦一点,因为栈是同一边进同一边出,而队列是尾巴进,脑袋出。
举个栗子
1、先加入一个元素
a,那么需要++tt, 就是tt==0, 然后要求a出队,就是hh++, 这时,hh=1, 现在队列为空,hh>tt。
2、因为数组的特点,在数组后面增加元素很方便,在头部增加元素很麻烦,所以设计了hh在左,tt在右的策略,出队hh++, 入队++tt
3、使用数组模拟队列的另一个好处,就是可以遍历队列中的每一个数字,这和用数组模拟栈是一样的,这也是STL比不了的。
普通队列解法
#include <bits/stdc++.h>using namespace std;
const int N = 1e5 + 10;
int q[N], hh, tt = -1;
int main() {int n;cin >> n;while (n--) {string op;cin >> op;if (op == "push") cin >> q[++tt];else if (op == "empty")hh > tt ? cout << "YES" << endl : cout << "NO" << endl;else if (op == "query")cout << q[hh] << endl;else hh++;}return 0;
}
循环队列解法
#include <bits/stdc++.h>using namespace std;
const int N = 1e5 + 10;
int q[N], hh, tt;
int main() {int n;cin >> n;while (n--) {string op;cin >> op;if (op == "push") {cin >> q[tt++];if (tt == N) tt = 0; // 加冒了,就回到0} else if (op == "empty")hh == tt ? cout << "YES" << endl : cout << "NO" << endl;else if (op == "query")printf("%d\n", q[hh]);else {hh++;if (hh == N) hh = 0; // 加冒了,就回到0}}return 0;
}
单调队列
单调队列:队列元素之间的关系具有单调性(从队首到队尾单调递增/递减),队首和队尾都可以进行入队出队(即插入删除)操作
通常解决动态小区间中寻找极值问题。

一、滑动窗口
ACW 154 滑动窗口
单调队列模板题。
对于最小值来说,我们维护一个单调递增队列,
这是因为我们要让队列的头为该区间的最小值,那么后一个数要比头大,
因为是单调的,所以每一个进来的数,都应该比队列中的数大,所以是单调递增队列。
题目中还有一个限制条件, 那便是窗口大小为k, 所以我们要时刻维护队列中的数的下标大于当前下标减去k,
如果不满足该条件,就从队列头删去该数,可见单调队列是个双端队列,这也便是为什么不用栈的原因。
具体实现时,我们令head=0表示队列头, tail=-1表示队列尾,
那么问题来了,为什么head要为0,tail为-1呢?
试想一下,如果head不为0,那么当head=tail时,队列中到底是没有数还是有1个数呢?显然无法判断。
所以我们令head的值+1,当head<=tail时,队列中便是有值的,如果head>tail,队列便为空。
该数组为 [1 3 -1 -3 5 3 6 7],k为3。
我们用样例来模拟一下单调队列,以求最小值为例:
i=0,队列为空,1进队,[1]
i=1,3比1大,满足单调性,3进队,[1,3]
i=2,-1比3小,破坏单调性,3出队,-1比1小,1出队,队列为空,-1进队[-1],此时i>=k,输出队头,即-1
i=3,-3比-1小,-1出队,队列为空,-3进队[-3],输出-3
i=4,5比-3大,5进队,[-3,5],输出-3
i=5,3比5小,5出队,3比-3大,3进队,[-3,3],输出-3
i=6,-3下标为4,i-4=3,大于等于k,-3已不在区间中,-3出队,6比3大,6进队,[3,6],输出3
i=7,7比6大,7进队,[3,6,7],输出3
-1 -3 -3 -3 3 3
这样最小值便求完了,最大值同理,只需在判断时改变符号即可。

#include <iostream>using namespace std;/*
求最大值时,用单调队列存储当前窗口内的单调递减的元素,队头是窗口内的最大值,队尾是窗口内的最小值。
求最小值时,用单调队列存储当前窗口内的单调递增的元素,队头是窗口内的最小值,队尾是窗口内的最大值。
*/const int N = 1000010;
int a[N], que[N];int main()
{int n, k;scanf("%d%d", &n, &k);for(int i = 0; i < n; i ++) scanf("%d", &a[i]);int head = 0, tail = -1;for(int i = 0; i < n; i ++){// 下标为que[head] 的元素是否还在当前窗口的最左端,若不在,则单调队中队头为上个窗口中最小值的下标// 进行队头出队,head自动指向第一个比 a[que[head]] 小的元素下标,且在当前窗口内if(head <= tail && i - k + 1 > que[head]) head ++;// 若当前值小于等于队尾元素时,则队尾元素不可能称为窗口最小值// 则将队尾元素出队while(head <= tail && a[que[tail]] >= a[i]) tail --;// 下标入队,便于队头出队,方便处理下一个滑动窗口que[++ tail] = i;// 使用队头中的最小值if(i >= k - 1) printf("%d ", a[que[head]]);}puts("");// 求窗口最大值情况相似head = 0, tail = -1;for (int i = 0; i < n; i ++){if (head <= tail && i - k + 1 > que[head]) head ++;while (head <= tail && a[que[tail]] <= a[i]) tail --;que[++ tail] = i;if (i >= k - 1) printf("%d ", a[que[head]]);}}
相关文章:
数据结构--队列
一、队列是什么 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,队列是一种操作受限制的线性表。进行插入操作的端称为队尾&…...
Python绘图系统25:新增8种绘图函数
文章目录 常用绘图函数单选框的更改逻辑源代码 Python绘图系统: 前置源码: Python打造动态绘图系统📈一 三维绘图系统 📈二 多图绘制系统📈三 坐 标 轴 定 制📈四 定制绘图风格 📈五 数据生成导…...
(二) gitblit用户使用教程
(一)gitblit安装教程 (二) gitblit用户使用教程 (三) gitblit管理员手册 目录 网页访问git客户端设置推送错误配置查看当前配置 日常使用仓库分组my profile修改上传代码简洁 网页访问 点击Advanced... 点击Accept the Risk and Contiue 初始用户名和密码都是admin,点击login…...
8.3Jmeter使用json提取器提取数组值并循环(循环控制器)遍历使用
Jmeter使用json提取器提取数组值并循环遍历使用 响应返回值例如: {"code":0,"data":{"totalCount":11,"pageSize":100,"totalPage":1,"currPage":1,"list":[{"structuredId":&q…...
SNERT预备队招新CTF体验赛-Misc(SWCTF)
目录 1、最简单的隐写 2、旋转我 3、is_here 4、zip伪加密 5、压缩包密码爆破 6、我就藏在照片里 7、所以我放弃了bk 8、套娃 9、来自银河的信号 10、Track_Me 11、勇师傅的奇思妙想 1、最简单的隐写 下载附件后,图片格式并不支持打开 根据题目提示&…...
MySql017——组合查询
一、UNION作用 可用UNION操作符来组合数条SQL查询。 二、UNION 使用规则 1、UNION的使用很简单。所需做的只是给出每条SELECT语句,在各条语句之间放上关键字UNION。2、UNION必须由两条或两条以上的SELECT语句组成,语句之间用关键字UNION分隔ÿ…...
【0224】源码分析RelFileNode对smgr访问磁盘表文件的重要性(2)
1. RelFileNode的角色 RelFileNode 是一个结构体数据类型,声明于relfilenode.h(src\include\storage )头文件中,该数据类型十分重要,因为它 “提供所有我们需要知道的物理访问关系表的信息。” smgr要访问磁盘上面的数据表文件,则需要此RelFileNode提供必要信息。 可以说…...
2310C++λ中完美转发
原文 C11里面就引入了完美转发概念,通过它,可按参数实际类型转发参数. 元<型名 T>空 处理(T&t){输出<<"左值\n";} 元<型名 T>空 处理(T&&t){输出<<"右值\n";} 元<型名 T>空 测试转发(T&&t){处理(前向&…...
【C++11】std::function 包装器(又叫适配器),std::bind 绑定
文章目录 std::function 包装器1. 使用方法2. 包装器的应用场景:题目 - - 逆波兰表达式求值3. 成员函数 和 static 静态成员函数 使用 包装器 std::bind 适配器绑定1. 使用方法2. 调整参数 顺序3. 指定参数 / 参数个数的调整 std::function 包装器 std::function 包…...
Linux系统编程系列之线程
一、什么是线程 线程(Thread)是计算机中的基本执行单元,是操作系统调度的最小单位。线程是进程内的一个独立执行流程,一个进程可以包含多个线程,这些线程共享进程的资源,但每个线程都有自己的独立栈空间以及…...
CV面试知识点总结
一.卷积操作和图像处理中的中值滤波操作有什么区别? 1.1卷积操作 卷积操作是一种线性操作,通常用于特征的提取,通过卷积核的加权求和来得到新的像素值。1.2中值滤波 原文: https://blog.csdn.net/weixin_51571728/article/detai…...
Centos一键安装、切换各版本JDK
查看服务中的安装的jdk rpm -qa | grep java获取jdk各版本信息 yum -y list java*查看指定版本 yum -y list java*|grep 1.8安装jdk yum install java-11-openjdk当服务器中有多个版本jdk,切换指定jdk版本 alternatives --config java按照提示输入编号即可切换&…...
JavaWeb项目:smbms(mysql)
1.准备工作,创建数据库 CREATE DATABASE smbms;USE smbms;CREATE TABLE smbms_address (id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 主键ID,contact VARCHAR(15) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 联系人姓名,addressDesc VARCHAR(50) COLLATE u…...
shell脚本的多线程介绍
shell脚本的多线程介绍 shell脚本中,实现多线程可以使用以下方法: 1)使用&符号 在Shell中,可以使用&符号将命令放在后台执行,这样就可以同时执行多个命令。例如: #!/bin/bash command1 & #…...
周记之反思
9.25 这篇总结我承认,是在26号上午写的,那昨天晚上又聊天了,但是对比之前来说好很多了,所以26号上午也就是今天我起了个大早,然后把昨天的尾巴收了一下,没收完,先说说成果: 完成了…...
信创办公–基于WPS的EXCEL最佳实践系列 (数据整理复制粘贴)
信创办公–基于WPS的EXCEL最佳实践系列 (数据整理复制粘贴) 目录 应用背景操作步骤1、数据查找与替换2、复制或粘贴数据3、使用自动填充工具4、将数据拆分到多列5、应用数字格式 应用背景 数据的整理复制粘贴等在日常的工作中经常使用。本章内容主要学习…...
二极管的直流等效电路和微变等效电路
二级管的主要参数 1.IF(最大整流的电流) 二极管长期工作做能够通过电流的平均最大值:物理意义:功率电流值。 2.UR 二极管最高反向工作电压 需要留有裕度,通常能达到一半的裕度;UR不能等于UBR。 3.IR 未击穿…...
Python无废话-基础知识字典Dictionary详讲
“字典Dictionary” 是一种无序、可变且可嵌套的数据类型,用于存储键值对。字典使用花括号{}来定义,并用逗号分隔键值对。本文对字典常使用方法,创建字典、添加字典、删除字典、如何获取字典做了知识归纳。 字典有以下几个特征: …...
ChatGPT多模态升级,支持图片和语音,体验如何?
一、前言 9 月 25 日,ChatGPT 多模态增加了新的语音功能和图像功能。这些功能提供了一种新的、更直观的界面,允许我们与 ChatGPT 进行语音对话或展示我们正在谈论的内容。 ChatGPT 现在可以看、听、和说话了,而不单单是一个文本驱动的工具了。…...
(SAR)Sentinel-1影像自动下载
基于ASF网站提供的python代码,实现Sentinel-1影像的自动下载; 1、登录ASF网站 登录Sentinel-1影像ASF网站:https://search.asf.alaska.edu/; 点击网站最右侧Sign in图标,进行用户注册; 注册完用户之后&…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)
Name:3ddown Serial:FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名:Axure 序列号:8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...
【版本控制】GitHub Desktop 入门教程与开源协作全流程解析
目录 0 引言1 GitHub Desktop 入门教程1.1 安装与基础配置1.2 核心功能使用指南仓库管理日常开发流程分支管理 2 GitHub 开源协作流程详解2.1 Fork & Pull Request 模型2.2 完整协作流程步骤步骤 1: Fork(创建个人副本)步骤 2: Clone(克隆…...
深入解析 ReentrantLock:原理、公平锁与非公平锁的较量
ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...
