【priority_queue的使用及模拟实现】—— 我与C++的不解之缘(十六)

前言

​ priority_queue,翻译过来就是优先级队列,但是它其实是我们的堆结构(如果堆一些遗忘的可以看一下前面的文章复习一下【数据结构】二叉树——顺序结构——堆及其实现_二叉树顺序结构-CSDN博客),本篇文章就来使用并且模拟实现一下priority_queue。

priority_queue的使用

在这里插入图片描述

​ 这个容器接口就这些,使用起来比较简单:这里就简单使用一下。

int main()
{priority_queue<int> pq1;//无参构造int arr[] = { 1,5,8,9,2,10,6 };//使用一段迭代器区间构造(这里可以使用数组,因为原始指针可以像迭代器那样使用)priority_queue<int> pq2(arr, arr + sizeof(arr) / sizeof(arr[0]));//依次输出pq2while (!pq2.empty()){cout << pq2.top() << " ";pq2.pop();}cout << endl;//往pq1插入数据pq1.push(1);pq1.push(5);pq1.push(7);pq1.push(8);pq1.push(9);//依次输出pq1while (!pq1.empty()){cout << pq1.top() << " ";pq1.pop();}cout << endl;return 0;
}

输出结果如下:

10 9 8 6 5 2 1
9 8 7 5 1

​ 经过观察,我们会发现,默认构建的都是大堆,先看一下容器priority_queue 的定义

在这里插入图片描述

​ 这里有三个模版参数,第一个是数据类型,第二个是容器类型(默认是vector),第三个是compare 默认是 less(这个是一个仿函数,再模拟实现后面再讲解)。

我们不难发现,只有第三个模版参数才也可能控制是大堆还是小堆,(这里,我们如果要建小堆传**greater**即可)。

//建小堆
int main()
{priority_queue<int, vector<int>, greater<int>> pq1;pq1.push(9);pq1.push(7);pq1.push(5);pq1.push(3);pq1.push(2);while (!pq1.empty()){cout << pq1.top() << " ";pq1.pop();}cout << endl;return 0;
}
2 3 5 7 9

​ 这样就建了小堆;对于仿函数,在模拟实现之后,我相信就会有了深刻的理解。

priority_queue模拟实现

​ 通过看priority_queue的定义,我们不难发现其也是一个容器适配器,默认容器是vector;所以它的成员变量就是一个容器,其的每一个操作就是在容器中进行一系列操作。

先来看一下priotity_queue的大致内容:

namespace HL
{//默认——大堆template<class T, class Contianer = vector<T>, class Compare = less<T>>class priority_queue{//向下调整算法void AdjustDown(int parent){}//向上调整算法void AjustUp(int child){}public://默认构造priority_queue() {}//迭代器区间构造template<class InputIterator>priority_queue(InputIterator first, InputIterator last){}void push(const T& x) {}void pop() {}T& top() {}const T& top()const {}size_t size()const {}bool empty()const {}private:Contianer _con;};
}

1、向上调整算法

​ 所谓向上调整算法,就是向上调整当前节点,使其满足堆结构。

主要应用:插入节点时,最后一个节点(插入的节点)向上调整。

		//向上调整算法void AjustUp(int child){int parent = (child - 1) / 2;while (parent >= 0){if (_con[parent] < _con[child]){std::swap(_con[parent], _con[child]);}else{break;}child = parent;parent = (child - 1) / 2;}}

2、向下调整算法

​ 所谓向上调整算法,就是向下调整当前节点,使其满足堆结构。

主要应用:

  • 构造堆结构时,从最后一个节点的父节点开始依次向下调整,创建堆结构。
  • 删除节点时,第一个(堆顶)与最后一个(堆底)交换,然后让第一个(堆顶)节点向下调整。
    在这里插入图片描述
		void AdjustDown(int parent){int child = 2 * parent + 1;while (child < _con.size()){if (child < _con.size() - 1 && _con[child] < _con[child + 1]){child++;}if (_con[parent] < _con[child]){std::swap(_con[parent], _con[child]);}else{break;}parent = child;child = 2 * parent + 1;}}

3、构造函数

​ 构造函数有两种,一是默认构造函数,另一个就是使用迭代器区间构造。

1.默认构造

//默认构造
priority_queue() {}

2.迭代器区间构造

​ 迭代器区间,这里就先将数据插入到容器(vector)中,再从最后一个节点的父节点开始,依次往下调整建堆即可。

//迭代器区间构造
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);}
}	

4、push、pop、top

  • push: 插入数据,然后向上调整,保持堆结构。
void push(const T& x) 
{_con.push_back(x);AdjustUp(_con.size() - 1);
}
  • pop: 删除数据(删除堆顶数据),堆顶数据与堆低数据交换,然后从堆顶位置向下调整即可。
void pop() 
{std::swap(_con[0], _con[_con.size() - 1]);AdjustDown(0);
}
  • top: 返回堆顶数据
T& top() 
{return _con[0];
}
const T& top()const 
{return _con[0];
}

5、size、empty、swap

  • size: 返回堆中的数据个数
size_t size()const 
{return _con.size();
}
  • empty: 判断堆是否为空
bool empty()const 
{return _con.empty();
}
  • swap: 交换函数
void swap(priority_queue& pq)
{std::swap(_con, pq._con);
}

​ 到这里,priority_queue 大致就实现成功了一半,因为这里我们只实现了大堆。

接下来,我们来看一下仿函数,如何实现大小堆。

仿函数

​ 仿函数,也是STL中比较中要的内容;

那为什么叫做仿函数呢?因为,他实际上是一个类,这个类重载了operator() 这样,我们就可以像函数应用实使用这个类。

先来看一下仿函数**less**:

	//这里可以使用struct(默认成员是共有)template<class T>class Less{public:bool operator()(const T& x, const T& y){return x < y;}};template<class T>class Greater{public:bool operator()(const T& x, const T& y){return x > y;}};

​ 这里实现了仿函数**Less** 和**Greater**,我们可以像函数那样去使用这个类。

int main()
{HL::Less<int> l;cout << (l(11, 22)) << endl;return 0;
}

greater 与less类似,greater 是判断大的(就是,返回的是 x>y)。

​ 知道了仿函数,再回头看一下**priority_queue** 第三个模板参数,这个模板参数就是来控制大小堆的(默认是less,就是大堆;如果我们传greater 就是小堆。)

这样我们再修改一下,向上调整算法和向下调整算法,让我们可以通过这个模板参数来控制大小堆。

		//向下调整算法void AdjustDown(int parent){Compare com;int child = 2 * parent + 1;while (child < _con.size()){//if (child < _con.size() - 1 && _con[child] < _con[child + 1])if (child < _con.size() - 1 && com(_con[child], _con[child + 1])){child++;}//if (_con[parent] < _con[child])if (com(_con[parent] , _con[child])){std::swap(_con[parent], _con[child]);}else{break;}parent = child;child = 2 * parent + 1;}}//向上调整算法void AdjustUp(int child){Compare com;int parent = (child - 1) / 2;while (parent >= 0){//if (_con[parent] < _con[child])if (com(_con[parent] , _con[child])){std::swap(_con[parent], _con[child]);}else{break;}child = parent;parent = (child - 1) / 2;}}

​ 这里测试一下,使用模拟实现的堆进行排序,pq1建大堆,排降序;pq2建小堆,排升序。

void test_priority_queue()
{HL::priority_queue<int,vecotr<int>, HL::Less<int>> pq1;pq1.push(1);pq1.push(7);pq1.push(3);pq1.push(5);pq1.push(9);while (!pq1.empty()){cout << pq1.top() << " ";pq1.pop();}cout << endl;int arr[] = { 1,3,5,7,9,8,6,4,2 };HL::priority_queue<int,vector<int>,HL::Greater<int>> pq2(arr, arr + sizeof(arr) / sizeof(arr[0]));while (!pq2.empty()){cout << pq2.top() << " ";pq2.pop();}cout << endl;
}
int main()
{test_priority_queue();return 0;
}
9 7 5 3 1
1 2 3 4 5 6 7 8 9

​ 到这里,priority_queue 使用以及模拟实现就完成了,感谢各位的支持。

继续加油!!!

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

Greater<int>> pq2(arr, arr + sizeof(arr) / sizeof(arr[0]));while (!pq2.empty()){cout << pq2.top() << " ";pq2.pop();}cout << endl;
}
int main()
{test_priority_queue();return 0;
}
9 7 5 3 1
1 2 3 4 5 6 7 8 9

到这里,priority_queue 使用以及模拟实现就完成了,感谢各位的支持。

继续加油!!!

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2oul0hvapjsws

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/61401.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MacOS下的Opencv3.4.16的编译

前言 MacOS下编译opencv还是有点麻烦的。 1、Opencv3.4.16的下载 注意&#xff0c;我们使用的是Mac&#xff0c;所以ios pack并不能使用。 如何嫌官网上下载比较慢的话&#xff0c;可以考虑在csdn网站上下载&#xff0c;应该也是可以找到的。 2、cmake的下载 官网的链接&…

Kibana 本地安装使用

一 Kibana简介 1.1 Kibana 是一种数据可视化工具&#xff0c;通常需要结合Elasticsearch使用&#xff1a; Elasticsearch 是一个实时分布式搜索和分析引擎。 Logstash 为用户提供数据采集、转换、优化和输出的能力。 Kibana 是一种数据可视化工具&#xff0c;为 Elasticsear…

基于大数据爬虫数据挖掘技术+Python的网络用户购物行为分析与可视化平台(源码+论文+PPT+部署文档教程等)

#1024程序员节&#xff5c;征文# 博主介绍&#xff1a;CSDN毕设辅导第一人、全网粉丝50W,csdn特邀作者、博客专家、腾讯云社区合作讲师、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老…

【Android、IOS、Flutter、鸿蒙、ReactNative 】实现 MVP 架构

Android Studio 版本 Android Java MVP 模式 参考 模型层 model public class User {private String email;private String password;public User(String email, String password) {this.email = email;this.password = password;}public String getEmail() {return email;}…

android 使用MediaPlayer实现音乐播放--获取音乐数据

前面已经添加了权限&#xff0c;有权限后可以去数据库读取音乐文件&#xff0c;一般可以获取全部音乐、专辑、歌手、流派等。 1. 获取全部音乐数据 class MusicHelper {companion object {SuppressLint("Range")fun getMusic(context: Context): MutableList<Mu…

Android kotlin之配置kapt编译器插件

配置项目目录下的gradle/libs.versions.toml文件&#xff0c;添加kapt配置项&#xff1a; 在模块目录下build.gradle.kt中增加 plugins {alias(libs.plugins.android.application)alias(libs.plugins.jetbrains.kotlin.android)// 增加该行alias(libs.plugins.jetbrains.kotl…

HarmonyOs DevEco Studio小技巧31--卡片的生命周期与卡片的开发

Form Kit简介 Form Kit&#xff08;卡片开发服务&#xff09;提供一种界面展示形式&#xff0c;可以将应用的重要信息或操作前置到服务卡片&#xff08;以下简称“卡片”&#xff09;&#xff0c;以达到服务直达、减少跳转层级的体验效果。卡片常用于嵌入到其他应用&#xff0…

【GeekBand】C++设计模式笔记11_Builder_构建器

1. “对象创建” 模式 通过 “对象创建” 模式绕开new&#xff0c;来避免对象创建&#xff08;new&#xff09;过程中所导致的紧耦合&#xff08;依赖具体类&#xff09;&#xff0c;从而支持对象创建的稳定。它是接口抽象之后的第一步工作。典型模式 Factory MethodAbstract …

Ubuntu问题 - 显示ubuntu服务器上可用磁盘空间 一条命令df -h

目的 想要放我的 数据集 到新的ubuntu服务器中, 不知道存储空间够不够 开始 使用以下命令直接查看 df -h

.NET 9与C# 13革新:新数据类型与语法糖深度解析

记录&#xff08;Record&#xff09;类型 使用方式&#xff1a; public record Person(string FirstName, string LastName); 适用场景&#xff1a;当需要创建不可变的数据结构&#xff0c;且希望自动生成 GetHashCode 和 Equals 方法时。不适用场景&#xff1a;当数据结构需…

学习笔记030——若依框架中定时任务的使用

定时任务是软件开发中经常使用一个功能。 Java定时任务广泛应用于各种需要定时执行或周期性执行任务的场景&#xff0c;如&#xff1a; 数据备份&#xff1a;定期备份数据库中的数据&#xff0c;确保数据的安全性和可靠性。数据同步&#xff1a;如果有多个数据源需要同步数据…

出海第一步:搞定业务系统的多区域部署

出海的企业越来越多&#xff0c;他们不约而同开始在全球范围内部署应用程序。这样做的原因有很多&#xff0c;例如降低延迟&#xff0c;改善用户体验&#xff1b;满足一些国家或地区的数据隐私法规与合规要求&#xff1b;通过在全球范围内部署应用程序来提高容灾能力和可用性&a…

2024强化学习的结构化剪枝模型RL-Pruner原理及实践

[2024] RL-Pruner: Structured Pruning Using Reinforcement Learning for CNN Compression and Acceleration 目录 [2024] RL-Pruner: Structured Pruning Using Reinforcement Learning for CNN Compression and Acceleration一、论文说明二、原理三、实验与分析1、环境配置在…

【SpringCloud详细教程】-02-微服务环境搭建

精品专题&#xff1a; 01.《C语言从不挂科到高绩点》课程详细笔记 https://blog.csdn.net/yueyehuguang/category_12753294.html?spm1001.2014.3001.5482 02. 《SpringBoot详细教程》课程详细笔记 https://blog.csdn.net/yueyehuguang/category_12789841.html?spm1001.20…

BOM的详细讲解

BOM概述 BOM简介 BOM&#xff08;browser Object&#xff09;即浏览器对象模型&#xff0c;它提供了独立于内容而与浏览器窗口进行交互的对象&#xff0c;其核心对象是window。 BOM由一系列的对象构成&#xff0c;并且每个对象都提供了很多方法与属性 BOM缺乏标准&#xff…

Jenkins下载安装、构建部署到linux远程启动运行

Jenkins详细教程 Winodws下载安装Jenkins一、Jenkins配置Plugins插件管理1、汉化插件2、Maven插件3、重启Jenkins&#xff1a;Restart Safely插件4、文件传输&#xff1a;Publish Over SSH5、gitee插件6、清理插件&#xff1a;workspace cleanup system系统配置1、Gitee配置2、…

数据分析——Python绘制实时的动态折线图

最近在做视觉应用开发&#xff0c;有个需求需要实时获取当前识别到的位姿点位是否有突变&#xff0c;从而确认是否是视觉算法的问题&#xff0c;发现Python的Matplotlib进行绘制比较方便。 目录 1.数据绘制2.绘制实时的动态折线图3.保存实时数据到CSV文件中 import matplotlib.…

Unity 使用 ExcelDataReader 读取Excel表

文章目录 1.下载NuGet包2.通过NuGet包获取dll3.将dll复制unity Plugins文件夹下4.代码获取Excel表内容 1.下载NuGet包 通过NuGet下载&#xff1a; ExcelDataReaderExcelDataReader.DataSet离线下载方法 2.通过NuGet包获取dll 根据编译时程序集找到dll位置&#xff0c;找到与…

【vmware+ubuntu16.04】ROS学习_博物馆仿真克隆ROS-Academy-for-Beginners软件包处理依赖报错问题

首先安装git 进入终端&#xff0c;输入sudo apt-get install git 安装后&#xff0c;创建一个工作空间名为tutorial_ws&#xff0c; 输入 mkdir tutorial_ws#创建工作空间 cd tutorial_ws#进入 mkdir src cd src git clone https://github.com/DroidAITech/ROS-Academy-for-Be…

九、FOC原理详解

1、FOC简介 FOC&#xff08;field-oriented control&#xff09;为磁场定向控制&#xff0c;又称为矢量控制&#xff08;vectorcontrol&#xff09;&#xff0c;是目前无刷直流电机&#xff08;BLDC&#xff09;和永磁同步电机&#xff08;PMSM&#xff09;高效控制的最佳选择…