当前位置: 首页 > news >正文

C++: 优先级队列的模拟实现和deque

目录

 一、优先级队列

 1.1优先级队列 priority_queue介绍

1.2优先级队列的使用

1.3priority_queue的模拟实现

二、deque

2.1deque介绍

2.2deque的优缺点

2.3为什么选择deque作为stack和queue的底层默认容器


 一、优先级队列

 1.1优先级队列 priority_queue介绍

 1.11 优先级队列是一种容器适配器,根据严格的弱排序,它的第一个元素总是它所有元素中最大  的。

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),这种设计模式将一个类的接口转换成客户希望的另一个接口。比方说,在stack里面,把push接口转换成调用另一个容器的push_back,这个容器的类放在私有里,是根据初始化来定的,你希望这个底层容器是vector,那么在调用stack的push时,实际调用的就是vector的push_back进行插入元素操作。stack只是一个壳子,vector才是存储数据的底层,只是取数据和其他操作,得按照stack的特点进行。

容器适配器:虽然stack和queue也可以存放元素,但在STL中并没有将其划分在容器的行列,而是将其称之为容器适配器,因为stack和queue只是对其他容器进行了包装,STL中stack和queue默认底层容器使用deque。

deque后文介绍。

1.12 此上下文环境类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)

1.13 优先队列被实现为容器适配器,容器适配器就是将特定容器封装作为它的底层容器,queue提供一组特定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称之为优先队列的顶部。

1.14 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。底层容器应该可以通过随机访问迭代器访问,并支持以下操作:

empty(): 检测容器是否为空

size(): 返回容器的元素个数

front(): 返回容器的第一个元素

push_back(): 尾插一个元素进容器

pop_back(): 尾删一个元素

1.15 标准容器类vector和deque满足这些要求,如果没有指定特定容器类实例化priority_queue,一般使用vector作为其底层容器。

1.16 需要支持随机访问迭代器,以便始终在内部保持堆结构。容器适配器通过在需要时自动调用算法函数make_heap、push_heap和pop_heap来自动完成此操作。

1.2优先级队列的使用

优先级队列默认使用vector作为其底层存储结构的容器,在vector上又加了堆算法,令vector成为堆结构。因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。注意:默认情况下priority_queue是大堆。

priority_queue常用的函数和接口说明                                                                          

函数接口接口说明
priority_queue()/priority_queue(first,last)构造函数,第一个是构造一个空的优先级队列,第二个是用迭代器指向的区间进行构造
empty()队列是否是空
push(x)在优先级队列中插入一个元素x
pop()删除优先级队列中的堆顶元素
top()返回优先级队列中的堆顶元素

1.3priority_queue的模拟实现

为了防止前面数据结构的建堆都忘了,代码我会注释一下的。

#pragma once
#include <iostream>
using namespace std;
#include <assert.h>
#include <vector>
#include <list>namespace ting
{//创建一个仿函数,为元素的大小比较提供template<class T>struct less{//()操作符重载,这样less实例化的对象(如compare)在调用该函数时,就直接compare(),//括号里填参数就好。通过()操作符重载,把一个类对象当作函数来使用,非常方便。bool operator()(const T& p1, const T& p2){return p1 < p2;}};template<class T, class container = vector<int>,class Compare = less<T>>class priority_queue{Compare _compare;public:priority_queue(const Compare& comFunc = Compare())//Compare是一个类,后面
//没写类名意思是匿名对象,然后用comFunc给了它名字。
//得到名字的comFunc传给_comFunc,如果是less就less,Greater就 //Greater,不传就默认用Compare(),默认是比小                                      :_compare(comFunc){}template<class InputIterator>priority_queue(InputIterator first, InputIterator last, const Compare& comFunc = Compare()):_compare(comFunc){while (first != last){_cn.push_back(*first);++first;}//向下调整建大堆for (int i = (_cn.size() - 1 - 1) / 2; i >= 0; --i){AdjustDown(i);//从最后一颗树的父亲节点开始调,每次调一颗树}}void AdjustDown(size_t parent)//向下调整,从父亲节点开始调{size_t child = 2 * parent + 1;//孩子节点是父亲节点的2倍+1,设定为左孩子while (child < _cn.size())//比到最后一个孩子节点{//如果右孩子比左孩子大,左孩子就被右孩子取代。if (child + 1 < _cn.size() - 1 && _compare(_cn[child],_cn[child+ 1])){++child;}//父亲节点的值和两个孩子中更大的值比较,父亲节点小就交换位置,继续往下比if (child < _cn.size() && _compare(_cn[parent], _cn[child])){swap(_cn[parent], _cn[child]);parent = child;child = 2 * parent + 1;}else//如果父亲没有比孩子节点再小了,那后面的已经是一个堆了,不用再调整{break;}}}void AdjustUp(size_t child)//向上调整,从最后一个孩子节点开始调,所以是对尾插的元素进//行调整{size_t parent = (child - 1) / 2;while (child > 0){if (_compare(_cn[parent], _cn[child]))//如果父亲节点小于孩子,交换位置{swap(_cn[parent], _cn[child]);parent = child;child = 2 * parent + 1;}else//如果父亲节点不小于,那放在这不用管了。{break;}}}bool empty(){return _cn.empty();}size_t size(){return _cn.size();}void push(const T& x)//尾插时,这里已经是一个堆了,所以前面的不用调,从最后一个开始{_cn.push_back(x);AdjustUp(_cn.size()-1);//最后一个节点是孩子节点,适用于向上调整}void pop(){assert(!empty());swap(_cn[0], _cn[_cn.size() - 1]);_cn.pop_back();//删除头节点以后,最后面的节点到第一个,就要从第一个开始调AdjustDown(0);//所以是向下调整}const T& Top(){return _cn[0];}private:container _cn;};void test1(){int a[] = { 1, 4, 2, 7, 8, 9 };priority_queue<int> pq(a, a + 6);while (!pq.empty()){cout << pq.Top() << " ";pq.pop();}}
}

二、deque

2.1deque介绍

deque(双端队列):是一种双开口的“连续”空间的数据结构,双开口的含义是:可以再头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素,和list比较,空间利用率比较高。

deque并不是真正连续的空间,而是由一小段连续的小空间拼接而成,实际deque类似于一个动态的二维数组。

它先开辟一块指针数组,每一个指针都指向一块大小相等的空间(比如40个字节),平常插入删除元素就在指针指向的空间里操作,而且一般是从中间的空间开始用。这样当这块指针空间也被填满时,就重新动态开辟一块连续的空间。

双端队列底层是一块假象的连续空间,实际上是分段连续的,指针指向的空间是连续的。但指针指向某一块连续空间,和前一个指针指向的连续空间之间未必是连续的。后一个指针指向的连续空间是从堆区开辟的。要用的时候才开辟,这怎么连续?

2.2deque的优缺点

与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是比vector高的。

与list比较:其底层是连续空间,空间利用率比较高,不需要存储额外字段。

但是deque有一个致命缺陷不适合遍历,因为在遍历时,迭代器要频繁去检测是否移到某段小空间的边界,导致效率低下。而序列式场景中,经常需要遍历,大多数情况下优先考虑vector和list。deque的应用并不多,而且目前看到的应用就是作为STL中stack和queue的底层默认容器。

2.3为什么选择deque作为stack和queue的底层默认容器

1.stack和queue不需要遍历,因此stack和queue也没有迭代器,它们只需要在固定的一段进行操作就好。

2.在stack中元素增长时,deque比vector的效率高(扩容时不需要搬移大量数据);deque中的元素增长时,deque不仅效率高,而且内存使用率高。

这结合了deque的优点,而且完美避开了其缺点。

相关文章:

C++: 优先级队列的模拟实现和deque

目录 一、优先级队列 1.1优先级队列 priority_queue介绍 1.2优先级队列的使用 1.3priority_queue的模拟实现 二、deque 2.1deque介绍 2.2deque的优缺点 2.3为什么选择deque作为stack和queue的底层默认容器 一、优先级队列 1.1优先级队列 priority_queue介绍 1.11 优先级队…...

C++ socket epoll IO多路复用

IO多路复用通常用于处理单进程高并发&#xff0c;在Linux中&#xff0c;一切皆文件&#xff0c;一个socket连接会对应一个文件描述符&#xff0c;在监听多个文件描述符的状态应用中epoll相对于select和poll效率更高 epoll本质是系统在内核维护了一颗红黑树&#xff0c;监听的文…...

缓存IO与直接IO

IO类型 缓存 I/O 缓存 I/O 又被称作标准 I/O&#xff0c;大多数文件系统的默认 I/O 操作都是缓存 I/O。在 Linux 的缓存 I/O 机制中&#xff0c;数据先从磁盘复制到内核空间的缓冲区&#xff0c;然后从内核空间缓冲区复制到应用程序的地址空间&#xff08;用户空间&#xff0…...

输入输出(3)——C++的标准输入流

目录 一、cin 流 二、成员函数 get 获取一个字符 (一)无参数的get函数。 (二)有一个参数的get函数。 (三&#xff09;有3个参数的get函数 (四&#xff09;用成员函数 getline 函数读取一行字符 (五&#xff09;用成员函数 read 读取一串字符 (六&#xff09;istream 类…...

[力扣题解] 344. 反转字符串

题目&#xff1a;344. 反转字符串 思路 双指针法 代码 class Solution { public:void reverseString(vector<char>& s) {int i, j, temp;for(i 0, j s.size()-1; i < j; i, j--){temp s[j];s[j] s[i];s[i] temp;}} };...

找不到msvcr110.dll无法继续执行代码的原因分析及解决方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是找不到msvcr110.dll文件。这个错误通常发生在运行某些程序或游戏时&#xff0c;系统无法找到所需的动态链接库文件。为了解决这个问题&#xff0c;下面我将介绍5种常见的解决方法。 一&#…...

深入理解数仓开发(一)数据技术篇之日志采集

前言 今天开始重新回顾电商数仓项目&#xff0c;结合《阿里巴巴大数据之路》和尚硅谷的《剑指大数据——企业级电商数据仓库项目实战 精华版》来进行第二次深入理解学习。之前第一次学习数仓&#xff0c;虽然尽量放慢速度力求深入理解&#xff0c;但是不可能一遍掌握&#xff0…...

Edge浏览器:重新定义现代网页浏览

引言 - Edge的起源与重生 Edge浏览器&#xff0c;作为Microsoft Windows标志性的互联网窗口&#xff0c;源起于1995年的Internet Explorer。在网络发展的浪潮中&#xff0c;IE曾是无可争议的霸主&#xff0c;但随着技术革新与用户需求的演变&#xff0c;它面临的竞争日益激烈。…...

HDFS,HBase,MySQL,Elasticsearch ,MongoDB分别适合存储什么特征的数据?

HDFS&#xff08;Hadoop Distributed File System&#xff09;通常用于存储大规模数据&#xff0c;适合存储结构化和非结构化数据&#xff0c;例如文本文件、日志数据、图像和视频等。 HBase是基于Hadoop的分布式数据库&#xff0c;适合存储大量非结构化和半结构化的数据&…...

ArcGIS中离线发布路径分析服务,并实现小车根据路径进行运动

ArcGIS中离线发布路径分析服务&#xff0c;您可以按照以下步骤操作&#xff1a; 准备ArcMap项目&#xff1a; 打开ArcMap并加载包含网络分析图层的项目。在ArcMap中&#xff0c;使用 Network Analyst Toolbar 或 Catalog 创建网络数据集&#xff08;Network Dataset&#xff09…...

时政|医疗结果互认

背景&#xff08;存在的问题&#xff09; 看同一种病&#xff0c;换一家医院甚至换一个院区、换一个科室&#xff0c;检查检验还得再来一遍&#xff0c;费钱又费时。开展检查检验结果互认&#xff0c;可以明显减轻患者就医负担。患者不用做重复检查&#xff0c;也可节约就医时…...

华为OD机试【找出通过车辆最多颜色】(java)(100分)

1、题目描述 在一个狭小的路口&#xff0c;每秒只能通过一辆车&#xff0c;假设车辆的颜色只有 3 种&#xff0c;找出 N 秒内经过的最多颜色的车辆数量。 三种颜色编号为0 &#xff0c;1 &#xff0c;2。 2、输入描述 第一行输入的是通过的车辆颜色信息[0,1,1,2] &#xff0…...

hyperf 多对多关联模型

这里使用到三张表&#xff0c;一张是用户&#xff08;users&#xff09;&#xff0c;一张是角色(roles)&#xff0c;一张是用户角色关联表(users_roles)&#xff0c; 首先创建用户模型、角色模型 php bin/hyperf.php gen:model users php bin/hyperf.php gen:model rolesusers…...

每日力扣刷题day03(从零开始版)

文章目录 2024.5.24&#xff08;5题&#xff09;2828.判别首字母缩略词题解一题解二 1365.有多少小于当前数字的数字题解一题解二题解三 2469.温度转换题解一题解二 1502.判断能否形成等差数列题解一题解二 2351.第一个出现两次的字母题解一题解二 2024.5.24&#xff08;5题&am…...

误差反向传播简介与实现

误差反向传播 导语计算图反向传播链式法则 反向传播结构加法节点乘法节点 实现简单层加法乘法 激活函数层实现ReLUSigmoid Affine/Softmax层实现Affine基础版批版本 Softmax-with-Loss 误差反向传播实现梯度确认总结参考文献 导语 书上在前一章介绍了随机梯度下降法进行参数与…...

ATmega328P加硬件看门狗MAX824L看门狗

void Reversewdt(){ //硬件喂狗&#xff0c;11PIN接MAX824L芯片WDIif (digitalRead(11) HIGH) {digitalWrite(11, LOW); //低电平} else {digitalWrite(11, HIGH); //高电平 }loop增加喂狗调用 void loop() { …… Reversewdt();//喂狗 }...

【Redis】 String类型的内部编码与使用环境

文章目录 &#x1f343;前言&#x1f334;内部编码&#x1f384;典型使用场景&#x1f6a9;缓存功能&#x1f6a9;计数&#xff08;Counter&#xff09;功能&#x1f6a9;共享会话&#xff08;Session&#xff09;&#x1f6a9;验证码功能 ⭕总结 &#x1f343;前言 本篇文章重…...

HarmonyOS interface router scale pageTransition SlideEffect.Left ArkTS ArkUI

&#x1f3ac;️create Component export default struct TitleBar {build(){Row(){Text(transition).fontSize(30fp).fontColor(Color.White)}.width(100%).height(8%).backgroundColor(#4169E1).padding({left:10})}}&#x1f39e;️interface export interface IList{ti…...

Go语言(Golang)的开发框架

在Go语言&#xff08;Golang&#xff09;的开发中&#xff0c;有多种开发框架可供选择&#xff0c;它们各自具有不同的特点和优势。以下是一些流行的Go语言开发框架&#xff0c;选择Go语言的开发框架时&#xff0c;需要考虑项目需求、团队熟悉度、社区支持、框架性能和可维护性…...

Python入门第三课——Python 数据类型(详细)

文章回顾 Python入门第一课——Python起步安装、Sublime Text安装教程&#xff0c;环境配置Python入门第二课——Python的变量和简单数据类型 目录 文章回顾前言一、Python的详细数据类型二、各种数据类型和使用方法1.Number&#xff08;数字&#xff09;2、String&#xff08…...

Pi0模型快速体验:一键启动Web演示,免配置玩转机器人控制

Pi0模型快速体验&#xff1a;一键启动Web演示&#xff0c;免配置玩转机器人控制 1. 项目概述 Pi0是一个创新的视觉-语言-动作流模型&#xff0c;专为通用机器人控制设计。这个项目最吸引人的地方在于它提供了一个开箱即用的Web演示界面&#xff0c;让用户无需复杂的配置就能体…...

OpenClaw性能调优实战:提升Kimi-VL-A3B-Thinking多模态响应速度的5个技巧

OpenClaw性能调优实战&#xff1a;提升Kimi-VL-A3B-Thinking多模态响应速度的5个技巧 1. 问题背景与性能瓶颈分析 最近我在本地部署了Kimi-VL-A3B-Thinking多模态模型&#xff0c;并通过OpenClaw与之对接&#xff0c;构建了一个自动化图文处理的工作流。但在实际使用中发现&a…...

Glide:Android图片加载的瑞士军刀,真的有这么神?

Glide&#xff1a;Android图片加载的瑞士军刀&#xff0c;真的有这么神&#xff1f; Glide 是什么&#xff0c;为何选择它 在 Android 开发的世界里&#xff0c;图片加载是一个绕不开的重要环节。想象一下&#xff0c;在一个社交类 APP 中&#xff0c;用户的头像、发布的照片&a…...

C/C++头文件防护:#pragma once原理与实践

1. #pragma once 的基本概念与作用在C/C项目开发中&#xff0c;头文件包含管理是个看似简单却暗藏玄机的问题。我第一次意识到它的重要性是在参与一个跨平台嵌入式项目时&#xff0c;某个模块因为头文件重复包含导致的结构体重定义错误&#xff0c;让整个团队排查了整整两天。而…...

红外遥控技术原理与工程实践详解

1. 红外遥控的基本原理红外遥控技术是现代电子设备中最常见的无线控制方式之一。它的核心原理是利用红外光作为信息载体&#xff0c;在发射端和接收端之间建立通信链路。这种看似简单的技术背后&#xff0c;其实蕴含着精妙的物理原理和电子设计。红外光的波长范围通常在700纳米…...

大模型时代,这5大热门职业让你月入50K!错过等一年!

在数字技术迭代速度不断加快的当下&#xff0c;人工智能领域的大模型&#xff08;Large Models&#xff09; 已从实验室走向产业落地&#xff0c;成为重构各行业生产模式、驱动创新升级的核心引擎。凭借在数据处理、模式识别、复杂任务决策等方面的超强能力&#xff0c;大模型不…...

STM32智能遥控婴儿车设计与实现

1. 项目概述这个基于STM32的智能遥控婴儿车项目&#xff0c;是我在去年为朋友家新生儿设计的实用型作品。当时朋友抱怨市面上智能婴儿车要么功能单一&#xff0c;要么价格昂贵&#xff0c;于是萌生了DIY一个多功能、低成本解决方案的想法。经过三个月的迭代开发&#xff0c;最终…...

2025届必备的十大降AI率平台推荐

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 为了降低文本生成痕迹&#xff0c;针对知网AI检测系统的核心评估机制&#xff0c;要从语义连…...

GLM-. 全面支持与 Gemini CLI 集成:HagiCode 的多模型进化之路赂

1. 流图&#xff1a;数据的河流 如果把传统的堆叠面积图想象成一块块整齐堆叠的积木&#xff0c;那么流图就像一条蜿蜒流淌的河流&#xff0c;河道的宽窄变化自然流畅&#xff0c;波峰波谷过渡平滑。 它特别适合展示多个类别数据随时间的变化趋势&#xff0c;尤其是当你想强调整…...

面试题设计模式

策略模式&#xff1a;定义了一组算法&#xff0c;将每个算法都封装起来&#xff0c;并且使它们之间可以互换。 模板方法模式&#xff1a;模板的价值就在于骨架的定义&#xff0c;骨架内部将问题处理的流程已经定义好&#xff0c;通用的处理逻辑一般由父类实现&#xff0c;个性化…...