C++priority_queue模拟实现

C++priority_queue模拟实现

  • 1.priority_queue基本概念
  • 2.priority_queue基本结构
  • 3.size()成员函数
  • 4.empty()成员函数
  • 5.top()成员函数
  • 6.push()成员函数
  • 7.pop()成员函数
  • 8.构造函数
  • 9.完整代码

🌟🌟hello,各位读者大大们你们好呀🌟🌟
🚀🚀系列专栏:【C++的学习】
📝📝本篇内容:priority_queue基本概念;priority_queue基本结构;size()成员函数;empty()成员函数;top()成员函数;push()成员函数;pop()成员函数;构造函数;完整代码
⬆⬆⬆⬆上一篇:C++模拟实现queue
💖💖作者简介:轩情吖,请多多指教(> •̀֊•́ ) ̖́-

1.priority_queue基本概念

priority_queue是我们常说的优先级队列,是一个容器适配器,它底层默认使用了vector容器,并且在此基础上使用了堆算法。因为牵扯到了堆,那就跟二叉树搭上了点关系。我们的二叉树中有一种树叫做完全二叉树,什么是完全二叉树呢?
完全二叉树:前N-1层是满的,最后一层可以不满,但是必须从左往右是连续的。要注意的是满二叉树是一种特殊的完全二叉树
在这里插入图片描述
根据它的这个特性(没有任何节点漏洞),我们可以将完全二叉树存储到数组中,在C++中我们就可以把它放入vector中,这种将数组的方式来表述tree称为隐式表述法
那么任何一个节点求它的父节点以及左右子节点公式如下:
若i>0,i位置结点的双亲序号:(i-1)/2=parent;i=0,i为根节点编号,无双亲结点
设n为数组的大小,若2i+1<n,左孩子序号:2i+1=leftchild;2i+1>=n否则无左孩子
设n为数组的大小,若2i+2<n,右孩子序号:2i+2=rightchild;2i+2>=n否则无右孩子

前面说了堆算法是建立在树上的,那么什么是堆呢?
我们的堆分为两种,大根堆或者是小根堆
大堆:树中所有的父亲都大于等于孩子
小堆:树中的所有父亲都小于等于孩子

优先级队列只能在底端加入元素,从顶端取出元素,这也是为什么是队列原因,并且我们取出的值是所有元素中最大的或者最小的(优先队列中位于顶部的元素)
在这里插入图片描述

2.priority_queue基本结构

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <vector>
using namespace std;
namespace lnb
{//用来比较的仿函数template<class T>struct less{bool operator()(const T& x,const T& y)const{//less是<,greater是>return x < y;}};template<class T>struct greater{bool operator()(const T& x, const T& y)const{return x > y;}};template<class T, class Container=vector<T>, class Compare=less<T>>class priority_queue{public:private:Container _con;//用来存储完全二叉树Compare _com;//用来比较的方法};}

3.size()成员函数

		//有效元素个数size_t size()const{return _con.size();}

4.empty()成员函数

	//判空bool empty()const{return _con.empty();}

5.top()成员函数

		//获取最大或最小的元素(位于顶部,即下标为0的元素)const T& top()const{return _con[0];}

在这里插入图片描述
所获取的值如上图

6.push()成员函数

		void push(const T& val){//1.先进行插入_con.push_back(val);//2.进行向上调整AdjustUp(_con.size()-1);}private:void AdjustUp(int child){//1.先找到父节点int parent = (child - 1) / 2;//公式前面讲过while (child > 0)//保证不超过根节点,最后一次循环只能是child为1或2,parent为0{//2.判断是否父节点小于(大于)孩子节点//if(Compare()(_con[parent],_con[child]))//使用匿名对象来判断也可以if (_com(_con[parent], _con[child]))//默认是大堆,是判断是否父节点小于孩子节点{//3.进行交换swap(_con[parent], _con[child]);//4.调整parent,child,继续向上调整直到不需要调换或者到根节点child = parent;//父节点成为孩子节点继续往上调整parent = (child - 1) / 2;}else{//已经不需要调整了break;}}}

在这里插入图片描述
当把元素插入后,只需要进行一个向上调整即可,我们默认是大堆哈,这是为了保证当我们大堆的一个结构,所有的父结点大于孩子节点。因此插入的一个元素需要进行调整,如果它大于自己的父结点,就往上调整和父节点进行交换,孩子节点就到了父节点的位置,然后继续向上调整直到父节点大于孩子节点或者调整到根节点结束
上面的代码中,我们使用到了仿函数来进行判断,但是我们如果没有它呢?那么对于泛型编程是一个巨大的问题,使用者无法通过外部的模板参数来控制内部的比较,只能通过直接的><来判断。

7.pop()成员函数

		void pop(){//1.删除的是最大(最小)的元素,所以先将_con[0]和_con[_con.size()-1]交换swap(_con[0], _con[_con.size() - 1]);//2.容器进行尾删_con.pop_back();//3.交换后,就可以将_con[0]向下调整AdjustDown(0);}private://向下调整void AdjustDown(int parent)//默认为大堆{//1.先求出左孩子节点int child = parent * 2 + 1;while (child < _con.size())//保证孩子节点不会超过容器的大小{//2.保证大(小)根堆的特性,选出孩子节点中较大(小)的那个if (child+1<_con.size()&&_com(_con[child],_con[child + 1]))//确保右孩子的存在{child++;}//3.进行判断是否父节点小于(大于)孩子节点if (_com(_con[parent], _con[child])){//4.进行交换swap(_con[parent], _con[child]);//5.孩子节点成为父节点,并重新找左孩子节点parent = child;child = parent * 2 + 1;}else{//父节点大于(小于)孩子节点即可结束break;}//6.一直调整,直到父节点大于(小于)孩子节点或者父节点没有孩子节点了}}

在这里插入图片描述 上面已经给出了代码和交换的图片,我们首先来讲一下为什么需要通过交换才能删除这个最大(最小)元素,究其原因还是它在根节点的原因,没有办法对它进行一个直接删除,一旦直接删除,就会导致整体的一个堆结构就乱掉了,那么最好的方法就是和尾元素进行交换,然后进行向下调整,这样不但保证了结构的完整性,效率还高
向上调整如下图:
在这里插入图片描述

8.构造函数

	//使用迭代器构造template<class InputIterator>priority_queue(InputIterator first, InputIterator last):_con(first,last){//完全混乱的结构,需要进行调整//第一个-1是找到最后一个元素,第二个-1是为了找到父节点int end = ((_con.size() - 1) - 1) / 2;//找到最后一个元素的父节点while (end >= 0)//直到调整到根节点{AdjustDown(end);//对于子树进行从下往上挨个进行向下调整end--;}}//默认构造函数priority_queue(){}

默认构造就没什么好讲的,主要是使用迭代器构造,这个也是一个难点,给一堆混乱的数据,如何变成符合堆特性
在这里插入图片描述
想要保证一组毫无序列的元素变成堆,就需要保证每一个子树的父节点都大于(小于)孩子节点,因此我们只能从最后一棵子树开始向下调整,这样当调整到上一层时,下层都已经是堆了,只需要对当前节点也是向下调整即可。一直到根节点完成最后一次向下调整就可以完成堆的构建。

9.完整代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <vector>
using namespace std;
namespace lnb
{//用来比较的仿函数template<class T>struct less{bool operator()(const T& x,const T& y)const{//less是<,greater是>return x < y;}};template<class T>struct greater{bool operator()(const T& x, const T& y)const{return x > y;}};template<class T, class Container=vector<T>, class Compare=less<T>>class priority_queue{public://使用迭代器构造template<class InputIterator>priority_queue(InputIterator first, InputIterator last):_con(first,last){//完全混乱的结构,需要进行调整//第一个-1是找到最后一个元素,第二个-1是为了找到父节点int end = ((_con.size() - 1) - 1) / 2;//找到最后一个元素的父节点while (end >= 0)//直到调整到根节点{AdjustDown(end);//对于子树进行从下往上挨个进行向下调整end--;}}//默认构造函数priority_queue(){}//有效元素个数size_t size()const{return _con.size();}//判空bool empty()const{return _con.empty();}//获取最大或最小的元素(位于顶部,即下标为0的元素)const T& top()const{return _con[0];}void push(const T& val){//1.先进行插入_con.push_back(val);//2.进行向上调整AdjustUp(_con.size() - 1);}void pop(){//1.删除的是最大(最小)的元素,所以先将_con[0]和_con[_con.size()-1]交换swap(_con[0], _con[_con.size() - 1]);//2.容器进行尾删_con.pop_back();//3.交换后,就可以将_con[0]向下调整AdjustDown(0);}private://向下调整void AdjustDown(int parent)//默认为大堆{//1.先求出左孩子节点int child = parent * 2 + 1;while (child < _con.size())//保证孩子节点不会超过容器的大小{//2.保证大(小)根堆的特性,选出孩子节点中较大(小)的那个if (child+1<_con.size()&&_com(_con[child],_con[child + 1]))//确保右孩子的存在{child++;}//3.进行判断是否父节点小于(大于)孩子节点if (_com(_con[parent], _con[child])){//4.进行交换swap(_con[parent], _con[child]);//5.孩子节点成为父节点,并重新找左孩子节点parent = child;child = parent * 2 + 1;}else{//父节点大于(小于)孩子节点即可结束break;}//6.一直调整,直到父节点大于(小于)孩子节点或者父节点没有孩子节点了}}void AdjustUp(int child){//1.先找到父节点int parent = (child - 1) / 2;//公式前面讲过while (child > 0)//保证不超过根节点,最后一次循环只能是child为1或2,parent为0{//2.判断是否父节点小于(大于)孩子节点//if(Compare()(_con[parent],_con[child]))//使用匿名对象来判断也可以if (_com(_con[parent], _con[child]))//默认是大堆,是判断是否父节点小于孩子节点{//3.进行交换swap(_con[parent], _con[child]);//4.调整parent,child,继续向上调整直到不需要调换或者到根节点child = parent;//父节点成为孩子节点继续往上调整parent = (child - 1) / 2;}else{//已经不需要调整了break;}}}private:Container _con;//用来存储完全二叉树Compare _com;//用来比较的方法};}

🌸🌸C++priority_queue模拟实现的知识大概就讲到这里啦,博主后续会继续更新更多C++的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!💪💪

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

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

相关文章

[STM32 HAL库]串口中断编程思路

一、前言 最近在准备蓝桥杯比赛&#xff08;嵌入式赛道&#xff09;&#xff0c;研究了以下串口空闲中断DMA接收不定长的数据&#xff0c;感觉这个方法的接收效率很高&#xff0c;十分好用。方法配置都成功了&#xff0c;但是有一个点需要进行考虑&#xff0c;就是一般我们需要…

嵌入式 工程配置

本次用的STM32F4芯片系列 目录 1. 新建文件夹 2. 新建文件夹下创建 3. 打开keil5 3.1.1 点击菜单栏project 点击new project 3.1.2. 选择刚刚新建的文件夹 3.1.3.将项目文件保存到Project文件夹里 3.1.4. 将项目命名这里命名为STM32 保存 3.1.5. 保存好后会跳出选择芯…

我的图形布局 组织结构图布局

组织结构图布局,有的人也叫它树状布局,在图形中是经常用到的布局算法.形成类似如下图的图形布局方式 首先创建一个类, public class TreeLayouter {private int m_space 40;/// <summary>/// 空间间隔/// </summary>public int Space{get { return m_space; }se…

计算机网络介质访问控制全攻略:从信道划分到协议详解!!!

一、信道划分介质访问控制 介质访问控制&#xff1a;多个节点共享同一个“总线型”广播信道时&#xff0c;可能发生“信号冲突” 应该怎么控制各节点对传输介质的访问&#xff0c;才能减少冲突&#xff0c;甚至避免冲突? 时分复用(TDM) 时分复用&#xff1a;将时间分为等长的“…

sql主从同步

今天给大家介绍两种mysql的主从同步方式&#xff1a;第一种是基于binlogzhu主从同步&#xff1b;第二种就是基于gtid的主从同步方式。 首先给大家介绍一下什么是sql的主从复制。 主从复制&#xff1a; 通过将MySQL的某一台主机&#xff08;master&#xff09;的数据复制到其…

计算机组成原理——数据表示(二)

当生活的压力和困惑缠绕在身边&#xff0c;我们往往需要振奋精神&#xff0c;勇往直前。无论在何种困境中&#xff0c;我们都要保持积极的态度和坚定的信念。将悲观的情绪抛之脑后&#xff0c;展现出坚强的意志力和无尽的活力。振奋精神意味着我们要战胜自己内心的负面情绪&…

Spring Boot整合Thymeleaf、JDBC Template与MyBatis配置详解

本文将详细介绍如何在Spring Boot项目中整合Thymeleaf模板引擎、JDBC Template和MyBatis&#xff0c;涵盖YAML配置、依赖版本匹配、项目结构设计及代码示例。 一、版本兼容性说明 Spring Boot版本与Java版本对应关系 Spring Boot 2.x&#xff1a;支持Java 8、11&#xff08;推…

概率论里的特征函数,如何用卷积定理去理解

概率论里的特征函数&#xff0c;如何用卷积定理去理解_哔哩哔哩_bilibili

论文笔记(六十二)Diffusion Reward Learning Rewards via Conditional Video Diffusion

Diffusion Reward Learning Rewards via Conditional Video Diffusion 文章概括摘要1 引言2 相关工作3 前言4 方法4.1 基于扩散模型的专家视频建模4.2 条件熵作为奖励4.3 训练细节 5 实验5.1 实验设置5.2 主要结果5.3 零样本奖励泛化5.4 真实机器人评估5.5 消融研究 6 结论 文章…

HashMap用法

一、构造方法 构造方法有4个。 1、手动声明初始容量及负载因子的构造函数。初容容量的最大值不能超过MAXIMUM_CAPACITY 2、手动声明初始容量的构造函数&#xff0c;负载因子是默认大小。 默认的负载因子是0.75 3、无参的构造函数&#xff0c;会指定默认的负载因子。容量是默…

Java基础 (一)

基础概念及运算符、判断、循环 基础概念 关键字 数据类型 分为两种 基本数据类型 标识符 运算符 运算符 算术运算符 隐式转换 小 ------>>> 大 强制转换 字符串 拼接符号 字符 运算 自增自减运算符 ii赋值运算符 赋值运算符 包括 强制转换 关系运算符 逻辑运算符 …

无人机在城市执法监管中的应用:技术革新与监管挑战

随着科技的不断进步&#xff0c;无人机技术在城市管理中的应用越来越广泛。无人机以其灵活性、高效性和低成本的优势&#xff0c;正在逐渐成为城市执法监管的得力助手。本文将探讨无人机在城市执法监管中的应用现状、技术优势以及面临的挑战。 无人机技术在城市执法监管中的应用…

AI模型提示词(prompt)优化-实战(一)

一、prompt作用 用户与AI模型沟通的核心工具&#xff0c;用于引导模型生成特定内容、控制输出质量、调整行为模式&#xff0c;并优化任务执行效果&#xff0c;从而提升用户体验和应用效果 二、prompt结构 基本结构 角色&#xff1a;设定一个角色&#xff0c;给AI模型确定一个基…

mac 电脑上安装adb命令

在Mac下配置android adb命令环境&#xff0c;配置方式如下&#xff1a; 1、下载并安装IDE &#xff08;android studio&#xff09; Android Studio官网下载链接 详细的安装连接请参考 Mac 安装Android studio 2、配置环境 在安装完成之后&#xff0c;将android的adb工具所在…

电子应用设计方案101:智能家庭AI喝水杯系统设计

智能家庭 AI 喝水杯系统设计 一、引言 智能家庭 AI 喝水杯系统旨在为用户提供个性化的饮水提醒和健康管理服务&#xff0c;帮助用户养成良好的饮水习惯。 二、系统概述 1. 系统目标 - 精确监测饮水量和饮水频率。 - 根据用户的身体状况和活动量&#xff0c;智能制定饮水计划。…

5G网络下移动机器人的图像和指令传输用于远程操作

论文标题 **英文标题&#xff1a;**Image and Command Transmission Over the 5G Network for Teleoperation of Mobile Robots **中文标题&#xff1a;**5G网络下移动机器人的图像和指令传输用于远程操作 作者信息 Thiago B. Levin,, Joo Miguel Oliveira,, Ricardo B. Sou…

AIGC视频生成国产之光:ByteDance的PixelDance模型

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍ByteDance的视频生成模型PixelDance&#xff0c;论文于2023年11月发布&#xff0c;模型上线于2024年9月&#xff0c;同时期上线的模型还有Seaweed&…

软件安全性测试报告如何编写?

在当今数字化时代&#xff0c;软件安全性问题愈发显得重要&#xff0c;软件产品的安全性已经成为企业竞争力的重要组成部分。而软件安全性测试报告是通过对软件系统进行全面的安全性测试后&#xff0c;整理出的关于其安全性状况、潜在风险及改进建议的专业文档。此报告旨在帮助…

从密码学原理与应用新方向到移动身份认证与实践

相关学习资料放下面啦&#xff01; 记得关注❤️&#xff5e;后续分享更多资料 通过百度网盘分享的文件&#xff1a;从密码学原理与应... 链接https://pan.baidu.com/s/1mHpHkvPuf8DUwReQkoYQlw?pwdGza7 提取码&#xff1a;Gza7 复制这段内容打开「百度网盘APP 即可获取」 记…

【玩转全栈】---基于YOLO8的图片、视频目标检测

本篇主要讲YOLO8的具体操作&#xff0c;想要了解YOLO的具体原理&#xff0c;可以去官网查询 目录 下载ultralytics库 开始检测 介绍 YOLOv8&#xff08;You Only Look Once Version 8&#xff09;是 YOLO 系列的最新版本&#xff0c;由 Ultralytics 开发并发布&#xff0c;是一…