【C++】deque以及优先级队列
容器适配器
- deque的介绍
- deque的原理介绍
- priority_queue的介绍与使用
- priority_queue的介绍
- priority_queue的使用
- constructor(构造函数)
- empty
- push
- pop
- top
- size
- priority_queue的模拟实现
- 仿函数
- 何为适配器
- 容器适配器
- deque的缺陷
- 选择deque作为适配器的理由
- STL标准库中对stack与queue的模拟实现
- stack的模拟实现
- queue的模拟实现
- 反向迭代器
deque的介绍
deque的原理介绍
deque(双端队列):是一种双开口的“连续”空间的数据空间,双开口的含义是:可以在头尾俩段进行插入和删除操作,且时间复杂度为O(1)。
与vector相比,头插效率高,不需要搬移元素;
与list相比,空间利用率高。
deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组。
双端队列底层是一段假象的连续空间,实际是分段连续的,为了维护其“整体连续”以及随机访问的假象,落在了deque的迭代器身上,因此deque的迭代器的设计就比较复杂。
下面是deque借助迭代器维护其假象连续的结构。
priority_queue的介绍与使用
priority_queue的介绍
- std::priority_queue
- template <class T, class Container = vector,
- class Compare = less< typename Container::value_type > > class priority_queue;
【说明】
1.优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它包含的元素中最大的。
2.此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。
3.优先级队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,priority_queue提供一组特定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先级队列的顶部。
4.底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作:
-
- empty():检测容器是否为空
-
- size():返回容器中有效元素个数
-
- front():返回容器中第一个元素的引用
-
- push_back():在容器尾部插入元素
-
- pop_back():删除容器尾部元素
5.标准容器类vector和deque满足这些要求,默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector
6.需要支持随机访问迭代器,以便始终在内部类保持堆结构。容器适配器通过在需要是自动调用算法函数make_heap、push_heap、pop_heao来自动完成此操作。
- pop_back():删除容器尾部元素
priority_queue的使用
优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用堆算法将vector中的元素构造成堆的结构,因此priority_queue就是堆,所以需要用到堆的位置,都可以考虑使用priority_queue。
【注意】默认情况下priority_queue是大堆。
constructor(构造函数)
- 构造一个空的优先级队列
priority_queue<int> pq;
empty
- 检测优先级队列是否为空,是返回true,否则返回false
priority_queue<int> pq;if (!pq.empty()){cout << "非空" << endl;}
push
- 在优先级队列中插入元素x
priority_queue<int> pq;pq.push(1);
pop
- 删除优先级队列中最大(最小)的元素,即删除堆顶元素。
【注意】:
1.默认情况下,priority_queue是大堆。
2.如果在priority_queue中放自定义类型的数据,用户需要在自定义类型中提供>或者<的重载。
top
- 返回优先级队列中最大(最小元素),即堆顶元素。
priority_queue<int> pq;pq.push(1);pq.push(3);pq.push(2);pq.push(7);pq.push(5);cout << pq.top() << endl;
size
- 返回元素个数
priority_queue<int> pq;pq.push(1);pq.push(3);pq.pop();cout << pq.size() << endl;
priority_queue的模拟实现
#pragma once
#include<iostream>
#include<vector>
#include<functional>namespace bit
{template<class T, class Container = std::vector<T>, class Comapre = std::less<T>>class priority_queue{private:void AdjustDown(int parent){Comapre com;size_t child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){++child;}if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void AdjustUp(int child){Comapre com;int parent = (child - 1) / 2;while (child > 0){if (com(_con[parent], _con[child])){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}public:priority_queue(){}template<class InputIterator>priority_queue(InputIterator first, InputIterator last){while (first != last){_con.push_back(*first);++first;}// 建堆for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--){AdjustDown(i);}}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}void push(const T& x){_con.push_back(x);AdjustUp(_con.size() - 1);}const T& top(){return _con[0];}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}
仿函数
仿函数(Functor)是一种重载函数调用运算符()或结构体,它可以像函数一样被调用。通过重载函数调用运算符,仿函数可以实现自定义的操作行为。
仿函数可以像普通函数一样接受参数,并返回结果。它可以用于函数对象的传递,函数指针的替代,算法的灵活性场景等。
template<class T>
class Less
{
public:bool operator()(T& val1, T& val2){return val1 < val2;}
};int main()
{Less<int> cmp;int num1 = 10;int num2 = 20;cout << cmp(num1, num2) << endl;return 0;
}
何为适配器
我们从前文的学习中以及了解到,stack与queue都是容器适配器。那么什么是适配器呢?
- 适配器是一种设计模式(设计模式是一套被反复使用的,多人知晓的,经过分类编目的,代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。
- 设配器(adaptor)是标准库中的一个通用概念。容器、迭代器和函数都有迭代器。本质上,一个迭代器是一种机制,能使某种事物的行为看起来像另外一种事物一样。
换句话来讲,适配器是将已有的东西进行相关的设配转换。
容器适配器
虽然在之前的学习中,stack与queue中也可以存放元素,但是在STL中并没有将其划分在容器的行列,而是将其称为容器适配器,这是因为stack和queue只是对其他容器的接口进行了包装,STL中stack与queue默认使用deque。
默认情况下,stack和queue是基于deque实现的,priority_queue是在vector之上实现的。
deque的缺陷
-
优势
与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是比vetcor高的。
与list相比,其底层是连续空间,空间的利用率比较高,不需要存储额外字段。 -
缺点
deque有一个致命的缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到某段小空间的边界,导致效率低下,而序列式场景中,可能需要经常遍历,因此在实际中,需要线性结构时,大多数情况下优先考虑vector和list,deque的应用并不多,而目前能看到的一个应用就是,STL用其作为stack和queue的底层数据结构。
选择deque作为适配器的理由
stack是一种后进先出的特殊线性数据结构,因此只要具有push_back()和pop_back()操作的线性结构,都可以作为stack的底层容器,比如vector和list都可以;
queue是先进先出的特殊线性数据结构,只要具有push_back()和pop_front()操作的线性结构,都可以作为queue的底层容器,比如list。
但是STL中对stack和queue默认选择deque作为其底层容器,主要是因为:
1.stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者俩端进行操作。
2.在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);queue中的元素增长时,deque不仅效率高,而且内存使用率高。
STL标准库中对stack与queue的模拟实现
stack的模拟实现
#include<deque>
namespace bite
{template<class T, class Con = deque<T>>//template<class T, class Con = vector<T>>//template<class T, class Con = list<T>>class stack{public:stack() {}void push(const T& x) { _c.push_back(x); }void pop() { _c.pop_back(); }T& top() { return _c.back(); }const T& top()const { return _c.back(); }size_t size()const { return _c.size(); }bool empty()const { return _c.empty(); }private:Con _c;};
}
queue的模拟实现
#include<deque>
#include <list>
namespace bite
{template<class T, class Con = deque<T>>//template<class T, class Con = list<T>>class queue{public:queue() {}void push(const T& x) { _c.push_back(x); }void pop() { _c.pop_front(); }T& back() { return _c.back(); }const T& back()const { return _c.back(); }T& front() { return _c.front(); }const T& front()const { return _c.front(); }size_t size()const { return _c.size(); }bool empty()const { return _c.empty(); }private:Con _c;};
}
反向迭代器
反向迭代器就是在容器中从尾元素像首元素反向移动的迭代器。对于反向迭代器,递增(以及递减)操作的含义都会颠倒过来。递增一个反向迭代器(++it)会移动到前一个元素;递减一个反向迭代器(- -it)会移动到下一个元素。
反向迭代器跟正向迭代器对称关系——镜像关系。
相关文章:

【C++】deque以及优先级队列
容器适配器 deque的介绍deque的原理介绍 priority_queue的介绍与使用priority_queue的介绍priority_queue的使用constructor(构造函数)emptypushpoptopsize priority_queue的模拟实现 仿函数何为适配器容器适配器deque的缺陷选择deque作为适配器的理由ST…...

手机如何播放电脑的声音?
准备工具: 有线耳机,手机,电脑,远控软件 1.有线耳机插电脑上 2.电脑安装pc版远控软件,手机安装手机端控制版远控软件 3.手机控制电脑开启声音控制 用手机控制电脑后,打开声音控制,电脑播放视频…...

系统架构设计师教程 第3章 信息系统基础知识-3.6 办公自动化系统(OAS)-解读
系统架构设计师教程 第3章 信息系统基础知识-3.6 办公自动化系统(OAS) 3.6.1 办公自动化系统的概念3.6.1.1 办公活动3.6.1.1 办公自动化的概念 3.6.2 办公自动化系统的功能3.6.2.1 事务处理3.6.2.1.1 单机系统3.6.2.1.2 多机系统 3.6.2.2 信息管理3.6.2.…...
解决Element UI 表格组件懒加载数据刷新问题
一、问题描述 element ui的table组件设置成懒加载时,遇到数据表格需要更新、删除等操作,子节点不会自动更新。 二、解决思路 刷新数据,就是重新调用load(),通过map记录已展开的节点,需要刷新…...

【系统架构设计 每日一问】二 MySql主从复制延迟可能是什么原因,怎么解决
主从复制的架构设计如下图所示: 同步原理 具体到数据库之间是通过binlog和复制线程操作的: Master的更新事件(update、insert、delete)会按照顺序写入bin-log中。当Slave连接到Master的后,Master机器会为Slave开启,binlog dump线程,该线程…...
Ubuntu Grub引导优化
配置文件 sudo vim /etc/default/grub修改参数 引导菜单等待时间 GRUB_TIMEOUT3自动引导上次选择的系统 如果安装了双系统或多系统,可以考虑配置此参数。 # 此参数默认值为0,引导第一个引导项 GRUB_DEFAULTsaved# 此参数默认没有,需要手…...

第3关 -- Git 基础知识
任务1: 破冰活动:自我介绍 任务2: 实践项目:构建个人项目 MeiHuaYiShu...
AttributeError: ‘WebDriver‘ object has no attribute ‘find_element_by_xpath‘
问题: 跑之前的python爬虫代码的时候报错 AttributeError: WebDriver object has no attribute find_element_by_xpath 源代码: elements self.driver.find_elements_by_xpath("//tbody[starts-with(id,normalthread)]/tr/th/a[1]")原因&…...
题解:小S与机房里的电脑 Computer_C++算法竞赛_贪心_二分答案_模拟_数据结构
文章目录 小S与机房里的电脑 Computer传统题题目描述输入格式输出格式样例样例输入 1样例输出 1样例输入 2样例输出 2 提示解题思路AC CodeEnd 小S与机房里的电脑 Computer 传统题 时间限制: 1000ms内存限制: 256MiB 题目描述 最近小S想带他的学生打组队娱乐赛,…...
Python @staticmethod、super().__init__()和self
最近在看代码,由于之前没有系统学习过Python,就有些知识点不是很清楚,这里整理一下,方便以后查阅。 Python中的staticmethod\super.init和self Python 装饰器staticmethod和classmethod的作用与区别作用区别代码演示 super() 函数…...

Linux网络:应用层协议HTTP(一)
一、什么是HTTP协议 虽然我们说, 应用层协议是我们程序猿自己定的. 但实际上, 已经有大佬们定义了一些现成的, 又非常好用的应用层协议, 供我们直接参考使用. HTTP(超文本传输协议)就是其中之一。 在互联网世界中,HTTP(HyperText Transfer Protocol&…...
Tomcat底层原理
Tomcat是一个开源的Java Servlet容器,它实现了Java Servlet和JavaServer Pages (JSP) 技术,用于运行Java Web应用。它是由Apache软件基金会开发和维护的。以下是对Tomcat底层原理的详细解析: 1. 启动流程 Tomcat的启动流程主要分为以下几个…...

【Linux】Linux环境设置环境变量操作步骤
Linux环境设置环境变量操作步骤 在一些开发过程中本地调试经常需要依赖环境变量的参数,但是怎么设置对小白来说有点困难,今天就介绍下具体的操作步骤,跟着实战去学习,更好的检验自己的技术水平,做技术还是那句话&…...

C语言:键盘录入案例
主要使用了scanf; scanf的使用方法和注意事项: 1.作用: 用于接收键盘输入的数据并赋值给对应的变量 2.使用方式; scanf("占位符",&变量名); 3.注意事项; 占位符后面的的变量要对应 第一个参数中不写换行 案例1…...
Nginx 中如何实现请求的排队机制?
Nginx 中如何实现请求的排队机制? 在当今数字化的时代,网站和应用的流量就如同潮水一般,时涨时落,时急时缓。想象一下,当流量如洪水猛兽般汹涌而来,服务器就像是那抗洪的堤坝,如果没有有效的管…...

synergy配置
今天介绍一个电脑同步软件synergy。 我们开发时一般会用两套设备,如果使用两套键盘操作起来会很麻烦,这个软件就是解决这个问题,可以使用一套键盘同时操作两台电脑,另一台作为客户端被控制。 安装 在两台电脑上各自下载安装syne…...

Qt开发网络嗅探器03
数据包分析 想要知道如何解析IP数据包,就要知道不同的IP数据包的包头结构,于是我们上⽹查查资料: 以太网数据包 ARP数据包 IPv4 IPv6 TCP UDP ICMP ICMPv6 根据以上数据包头结构,我们就有了我们的protocol.h文件,声明…...

抖音短视频seo矩阵系统源码开发技术分享(二)--SaaS开源
目录 市场背景分析 一、抖音短视频seo矩阵系统开发部署流程 二、 源码开发功能构思 三、 抖音短视频seo源码开发部署注意事项 四、 部分开发代码展示 市场背景分析 抖音短视频seo矩阵系统是通过不同平台不同账号之间建立联系,通过将同一品牌下不同平台不同账号…...
git-常用基础指令
一、基本指令 1. 配置用户名和邮箱 git config --global user.name "Your Name" git config --global user.email "your.emailexample.com"2. 初始化仓库 git init3. 克隆仓库 git clone <repository_url>4. 查看当前状态 git status5. 添加文件…...

Inconsistent Query Results Based on Output Fields Selection in Milvus Dashboard
题意:在Milvus仪表盘中基于输出字段选择的不一致查询结果 问题背景: Im experiencing an issue with the Milvus dashboard where the search results change based on the selected output fields. Im working on a RAG project using text data conv…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...

dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...

Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...