当前位置: 首页 > 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…...

html入门

<!DOCTYPE html><!--每个文件都要加上这个&#xff0c;是html文件的主题--> <html><!--查不多就是c预言的main函数&#xff0c;从头括到尾部--><head><meta http-equiv"Content-Type" content"text/html;charsetutf-8" /…...

蓝桥杯杨辉三角

PREV-282 杨辉三角形【第十二届】【蓝桥杯省赛】【B组】 &#xff08;二分查找 递推&#xff09;&#xff1a; 解析&#xff1a; 1.杨辉三角具有对称性&#xff1a; 2.杨辉三角具有一定规律 通过观察发现&#xff0c;第一次出现的地方一定在左部靠右的位置&#xff0c;所以从…...

【活动】开源与闭源大模型:探索未来趋势的双轨道路

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 开源与闭源大模型&#xff1a;探索未来趋势的双轨道路引言一、开源大模型&#…...

虚拟局域网(VLAN)

关键词&#xff1a;veth、vlan、bridge、iptables、nat、tcpdump、icmp、cidr、arp、路由表、计算机网络协议栈 前言 在过去的几十年里&#xff0c;互联网发展得非常快。许多新兴技术迅速崛起&#xff0c;也有不少曾经的主流技术被淘汰。然而&#xff0c;有些技术因为其基础性…...

内网穿透--Frp-简易型(速成)-上线

免责声明:本文仅做技术交流与学习... 目录 frp项目介绍: 一图通解: ​编辑 1-下载frp 2-服务端(server)开启frp口 3-kali客户端(client)连接frp服务器 4-kali生成马子 5-kali监听 6-马子执行-->成功上线 frp项目介绍: GitHub - fatedier/frp: A fast reverse proxy…...

Python库之Scrapy的简介、安装、使用方法详细攻略

Python库之Scrapy的简介、安装、使用方法详细攻略 简介 Scrapy是一个快速的、高层次的web抓取和web抓取框架&#xff0c;用于抓取网站数据并从页面中提取结构化的数据。Scrapy用途广泛&#xff0c;可以用于数据挖掘、信息处理或存储历史数据&#xff0c;以及各种其他用途。 …...

k8s配置pods滚动发布

背景 采用微服务架构部署的应用&#xff0c;部署方式都要用到容器化部署k8s容器编排&#xff0c;最近我在公司负载的系统也是用的上述架构部署&#xff0c;但是随着系统的运行&#xff0c;用户提的需求就会越多&#xff0c;每次更新的话都要停机发布&#xff0c;最用户侧来说就…...

C++vector的简单模拟实现

文章目录 目录 文章目录 前言 一、vector使用时的注意事项 1.typedef的类型 2.vector不是string 3.vector 4.算法sort 二、vector的实现 1.通过源码进行猜测vector的结构 2.初步vector的构建 2.1 成员变量 2.2成员函数 2.2.1尾插和扩容 2.2.2operator[] 2.2.3 迭代器 2…...

AWTK实现汽车仪表Cluster/DashBoard嵌入式GUI开发(七):快启

前言: 汽车仪表是人们了解汽车状况的窗口,而仪表中的大部分信息都是以指示灯形式显示给驾驶者。仪表指示灯图案都较为抽象,对驾驶不熟悉的人在理解仪表指示灯含义方面存在不同程度的困难,尤其对于驾驶新手,如果对指示灯的含义不求甚解,有可能影响驾驶的安全性。即使是对…...

基于springboot+vue的招聘信息管理系统

开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#xff1a;…...