C++优先级队列priority_queue模拟实现

priority_queue模拟实现

  • 1. priority_queue介绍
  • 2. priority_queue使用
    • 2.1 priority_queue显示定义
    • 2.2priority_queue接口使用
  • 3. 仿函数
  • 4. priority_queue模拟实现
    • 4.1 向上调整算法
    • 4.2 向下调整算法
    • 4.3 实现priority_queue的接口
    • 4.4 使用[仿函数](https://legacy.cplusplus.com/reference/functional/less/?kw=less)控制[priority_queue](https://legacy.cplusplus.com/reference/queue/priority_queue/?kw=priority_queue)默认大小堆
    • 4.5 priority_queue模拟实现代码

1. priority_queue介绍

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

2. priority_queue使用

2.1 priority_queue显示定义

priority_queue默认vector作为容器,默认情况下为大堆。

//默认
priority_queue<int> p1;
//显示为大堆
priority_queue<int, vector<int>, less<int>> p2;

若是容器为vector,结构为小堆

priority_queue<int, vector<int>, greater<int>> p3;

2.2priority_queue接口使用

成员函数说明
push往优先级队列中尾插数据
pop删除堆顶元素
top获取堆顶元素
empty判断优先级队列是否为空
size获取优先级队列的元素个数

示例:

void test()
{priority_queue<int> pq;pq.push(1);pq.push(3);pq.push(4);pq.push(5);pq.push(2);pq.push(6);pq.push(7);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}cout << endl;
}

3. 仿函数

在我们模拟实现priority_queue前,还需要了解仿函数。
仿函数(functor),就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。
示例:

struct Less
{bool operator()(const int& val1, const int& val2){return val1 < val2;}};int main()
{Less lessfunc;cout << lessfunc(1, 2) << endl;cout << lessfunc.operator()(1, 2) << endl;//显示调用cout << Less()(1, 2) << endl;//匿名对象return 0;
}

4. priority_queue模拟实现

priority_queue底层默认为堆,所以我们需要清楚向上调整算法和向下调整算法(这里以大堆例)。

4.1 向上调整算法

堆的向上调整算法思想(大堆):

  1. 目标结点与父结点相比较
  2. 如果目标结点大于父结点,目标结点就与父结点交换位置,后用当前新的位置作为目标结点继续向上调整。如果目标结点小于父结点,则停止向上调整。此时堆为大堆。
    在这里插入图片描述
    例子: 我们往堆中插入数据89
    在这里插入图片描述
    与父结点相比较大于父结点就交换,继续向上调整。
    在这里插入图片描述
    数据89大于88交换。
    在这里插入图片描述
    直到符合条件为止。
    在这里插入图片描述
    代码:
void adjust_up(size_t child)
{size_t parent = (child - 1) / 2;while (child > 0){if (c[child]>c[parent]){swap(c[child], c[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

4.2 向下调整算法

堆的向下调整算法思想(大堆):

  1. 目标结点与子结点比较
  2. 若是子结点大于目标结点,则与子结点交换位置。用当前新的位置作为目标结点继续向下调整。若是子结点小于目标结点,则停止向下调整,此时堆为大堆。
    示例:
    此时堆的左右子树都为大堆,因此我们可以将父结点向下调整。
    在这里插入图片描述
    判断子节点与当前位置数据的大小,大于则交换位置。
    在这里插入图片描述
    继续判断,向下调整。
    在这里插入图片描述
    直到符合目标结点大于子结点为止,此时堆为大堆。
    在这里插入图片描述
    代码:
void adjust_down(size_t parent)
{size_t  child = parent * 2 + 1;while (child < c.size()){//检查左结点是否大于右结点if (child + 1 < c.size() && c[child+1]>c[child]){child++;}if (c[child]>c[parent]){swap(c[child], c[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

4.3 实现priority_queue的接口

 bool empty() const{return c.empty();}size_t size() const{return c.size();}const T& top() {return c[0];}void push(const T& x){c.push_back(x);adjust_up(c.size()-1);}void pop(){swap(c[0], c[size() - 1]);c.pop_back();adjust_down(0);}

4.4 使用仿函数控制priority_queue默认大小堆

在这里插入图片描述

我们通过查阅文档可以发现,c++通过改变仿函数对priority_queue队列的默认大小堆的控制。
优势: 相比于函数指针,仿函数更加方便简单,更加利于控制(只需要跟换默认的仿函数)。

4.5 priority_queue模拟实现代码

namespace bit
{template <class T>struct less{bool operator()(const T& val1,const T& val2){return val1 < val2;}};template <class T>struct greater{bool operator()(const T& val1, const T& val2){return val1 > val2;}};template <class T, class Container = vector<T>, class Compare = less<T> >//这里默认容器是vector 因为要把优先级队列看成一个大堆,堆的物理结构是有序结构。class priority_queue{public:void adjust_up(size_t child){Compare com;size_t parent = (child - 1) / 2;while (child > 0){if (com(c[parent],c[child])){swap(c[child], c[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}}void adjust_down(size_t parent){size_t  child = parent * 2 + 1;while (child < c.size()){Compare com;if (child + 1< c.size() && com(c[child],c[child+1])){child++;}if (com(c[parent], c[child])){swap(c[child], c[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}bool empty() const{return c.empty();}size_t size() const{return c.size();}const T& top() {return c[0];}void push(const T& x){c.push_back(x);adjust_up(c.size()-1);}void pop(){swap(c[0], c[size() - 1]);c.pop_back();adjust_down(0);}private:Container c;Compare comp;};
};

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

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

相关文章

Springboot+Vue项目-基于Java+MySQL的流浪动物管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

MCP3008-I/SL 模数转换器ADC SPI接口 模拟信号采集

MCP3008-I/SL 模数转换器ADC 贴片SOIC16 MCP3008-I/SL 是一款模数转换器&#xff08;ADC&#xff09;&#xff0c;属于 SAR&#xff08;逐次逼近寄存器&#xff09;架构的 ADC。它具有以下特点&#xff1a; 8 通道单 ADC 最大采样率&#xff1a;200ksps&#xff08;千样点每秒…

为什么byte 的取值范围是 [-128,127]

在计算机中&#xff0c;byte&#xff08;字节&#xff09;是存储数据的基本单位&#xff0c;通常用8位二进制数字表示一个字节。在字节中&#xff0c;最高位的最左边一位是符号位&#xff0c;用来表示正负号&#xff0c;值为0表示正数&#xff0c;值为1表示负数。 如果将byte定…

URL过滤

什么是URL过滤&#xff1f; URL过滤是一种针对用户的URL请求进行上网控制的技术&#xff0c;通过允许或禁止用户访问某些网页资源&#xff0c;达到规范上网行为和降低安全风险的目的。 URL过滤可以基于URL分类、特定URL等多种方式限制URL访问。 URL过滤的主要作用如下&#xf…

Python Flask框架(一)初识Flask

Flask是使用Python编写的Web微框架。Web框架可以使我们不用关心底层的请求响应处理&#xff0c;更方便高效的编写Web程序。Flask有两个主要依赖&#xff0c;一个是WSGI&#xff08;Web Server Gateway Interface&#xff0c;web服务器网关接口&#xff09;工具集&#xff0c;另…

【文献解析】3D高斯抛雪球是个什么玩意

论文地址&#xff1a;https://arxiv.org/abs/2308.04079 项目&#xff1a;3D Gaussian Splatting for Real-Time Radiance Field Rendering 代码&#xff1a;git clone https://github.com/graphdeco-inria/gaussian-splatting --recursive 一、文章概述 1.1问题导向 辐射…

USB3.0接口——(1)基础知识

1.背景 USB 3.0是一种USB规范&#xff0c;该规范由英特尔等公司发起。 USB协议版本 命名约定 USB-IF组织引入命名约定&#xff0c;将端口列为 USB 5 Gbps、USB 10 Gbps、USB 20 Gbps 、USB 40 Gbps&#xff0c;而不使用版本号。获得 USB-IF 认证的 USB 产品的制造商会获得带…

SAP 长文本语言代码维护

在SAP中&#xff0c;我们发现长文本都是有语言代码的&#xff0c;如果需要新增一个语言代码的话&#xff0c;需要通过程序RSCPCOLA进行维护处理 具体实现步骤如下&#xff1a; 1. 输入事务码SE38&#xff0c;输入程序名RSCPCOLA&#xff0c;然后点击执行按钮 2. 维护信函语言…

sklearn的make_blobs函数

make_blobs是一个用于生成随机数据点的实用函数&#xff0c; from sklearn.datasets import make_blobs X,Y make_blobs(n_samples2000,n_features2,centers12,cluster_std0.05,center_box[-5,5],random_state21)n_samples: 要生成的样本数量。centers: 要生成的簇&#xff0…

电子书3D翻页制作技巧大揭秘,轻松将文档转化为逼真仿真书!

随着数字化时代的到来&#xff0c;电子书已成为阅读的主流形式之一。然而&#xff0c;普通的电子书往往缺乏纸质书的质感和互动性&#xff0c;让人感到有些遗憾。今天&#xff0c;将为你揭秘电子书3D翻页制作技巧&#xff0c;让你轻松将文档转化为逼真仿真书&#xff01; 1.要制…

LearnOpenGL(九)之材质

一、材质 在现实世界里&#xff0c;每个物体会对光产生不同的反应。比如&#xff0c;钢制物体看起来通常会比陶土花瓶更闪闪发光&#xff0c;一个木头箱子也不会与一个钢制箱子反射同样程度的光。在opengl中&#xff0c;我们可以针对每种表面定义不同的材质(Material)属性来模…

Mac 解决外接移动硬盘(NTFS格式)无法写入的问题

文章目录 1. 问题描述2. 解决步骤 1. 问题描述 MacOS 可以识别 NTFS 格式的磁盘&#xff0c;但是默认情况下是只读模式&#xff0c;即无法向 NTFS 格式的磁盘写入数据。这是因为 NTFS 是 Windows 系统默认的文件系统格式&#xff0c;而 MacOS 对 NTFS 的写入支持是有限的。 如…

指定地区|CSC高级研究学者赴澳大利亚访学交流

CSC高级研究学者均是正高或博导级的&#xff0c;学术背景较强&#xff0c;多数能DIY联系到国外合作机构。但也有些申请者因指定地域或学校&#xff0c;或须在短期内获取邀请函故而求助于我们。本案例D教授就指定澳大利亚的墨尔本地区&#xff0c;我们最终用维多利亚大学的邀请函…

JWK和JWT 学习

JWK和JWT 介绍 JWK (JSON Web Key) 和 JWT (JSON Web Token) 是现代Web应用程序中用于安全通信的两个重要概念。它们都是基于JSON的&#xff0c;并且是OAuth 2.0和OpenID Connect等协议的核心组成部分。 官方文档 JWT官方网站 JWK和JWK Set的RFC文档 JWT的RFC文档 JWK (JS…

Oopsie从80端口到获取root权限的渗透过程

Oopsie 需要用到的工具burpnmapnc手写代码信息收集 由于是靶场的原因单一没有子站所以收集到ip就可以nmap扫描 拿到IP第一件事就是扫描端口 nmap -T4 -sV -sC -sS 10.129.24.79 -T4:提升扫描速度 -sV&#xff1a;查看详细版本 -sC:使用默认类别的脚本进行扫描 可更换其他类别…

使用 Cython 加密 Python 代码防止反编译

文章目录 前言使用 Cython 加密 Python 代码环境Python 源代码编写 Cython 编译配置文件 编译查看输出文件使用 问题error: Microsoft Visual C 14.0 or greater is requiredpyconfig.h(59): fatal error C1083: 无法打开包括文件: “io.h”: No such file or directorydynamic…

Postgresql中JIT函数能否inline的依据function_inlinable

相关 《LLVM的ThinLTO编译优化技术在Postgresql中的应用》 在JIT inline函数的过程中&#xff0c;会通过函数的bc代码&#xff0c;经过一系列规则、成本的判断来决定函数能否Inline&#xff0c;本篇重点分析这段逻辑&#xff1a;function_inlinable。 总结速查&#xff1a; 入…

分布式链路追踪工具Sky walking详解

1&#xff0c;为什么要使用分布式链路追踪工具 随着分布式系统和微服务架构的出现&#xff0c;且伴随着用户量的增加&#xff0c;项目的体量变得十分庞大&#xff0c;一次用户请求会经过多个系统&#xff0c;不同服务之间调用关系十分复杂&#xff0c;一旦一个系统出现错误都可…

iphone忘记锁屏密码怎么解锁?这些解锁方法你必须知道!

在使用iPhone的过程中经常会遇到很多问题&#xff0c;比如忘记了iPhone的锁屏密码。面对这样的情况&#xff0c;许多用户可能会感到手足无措。别担心&#xff0c;本文将为您详细介绍iPhone忘记锁屏密码的解锁方法&#xff0c;让您轻松解决这一烦恼。 一、使用iTunes备份恢复 如…

以gitee为例的git入门使用指北

安装git 在linux中我们首先需要使用 sudo apt install git来下载git 在windows中可以下载msysGit 链接&#xff1a;https://git-scm.com/download/win gitee准备 申请账号 建立仓库 ​ 点击新建仓库 这里一般是私有库&#xff0c;点击创建&#xff0c;这时你就拥有一个线上…