优先级队列priority_queue以及仿函数的使用

目录

  • 优先级队列priority_queue
  • priority_queue的模拟实现
  • 仿函数

优先级队列priority_queue

优先级队列priority_queue是一种容器适配器,根据严格的弱排序标准,它默认第一个元素总是它所包含的元素中最大的

优先级队列默认使用vector作为底层存储数据的容器,在vector上又使用了堆排序的算法对数据进行排序,所以priority_queue就是堆。注意:priority_queue默认情况下是大堆

priority_queue是存在<queue>文件中,要使用只需要包queue文件就可以

所以以后有需要用到堆的位置,我们就不用手动实现一个堆了,可以直接使用priority_queue就可以

下面是优先级队列的定义:

template <class T, class Container = vector<T>,class Compare = less<typename Container::value_type> > class priority_queue;

第一个模板参数是放在适配器容器内元素的类型
第二个模板参数是适配器,默认为vector
第三个模板参数是一个仿函数,默认是less,为了保证默认是大堆

函数接口说明
priority_queue()构造一个空的优先级队列
priority_queue (InputIterator first, InputIterator last)用[first,last)迭代器区间构造一个优先级队列
empty()判空
top( )返回优先级队列中最大(最小元素),即堆顶元素
push(x)在优先级队列中插入元素x
pop()删除优先级队列中最大(最小)元素,即堆顶元素

下面我们使用优先级队列尝试一下:

void test1()
{priority_queue<int> pq;pq.push(1);pq.push(6);pq.push(9);pq.push(3);pq.push(0);pq.push(2);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}//输出 9 6 3 2 1 0 cout << endl;
}

如果我们先实现一个小堆,只需要改变第三个模板参数就可以,让第三个模板参数为greater<T>,因为我们指定了第三个模板参数,所以我们还需手动显式传第二个模板参数

下面我们实现一个小堆的priority_queue:

void test1()
{priority_queue<int,vector<int>,greater<int>> pq;pq.push(1);pq.push(6);pq.push(9);pq.push(3);pq.push(0);pq.push(2);while (!pq.empty()){cout << pq.top() << " ";pq.pop();}//输出 0 1 2 3 6 9cout << endl;
}



priority_queue的模拟实现

因为优先级队列的底层是堆排序,所以我们先完成堆排序中的向下调整,和向上调整

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

push函数,就是,先向底层适配器中插入一个元素,然后再调用向上调整法

void push(const T& t)
{_con.push_back(t);AdjustUp(_con.size() - 1);}

pop函数,先把适配器中首元素和尾元素交换,然后删除尾元素,再调用向下调整法

void pop()
{std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);
}

还有几个实现起来很简单的函数:

bool empty()
{return _con.empty();
}const T& top()
{return _con[0];
}size_t size()
{return _con.size();
}

当前完整代码:

namespace my_priority_queue
{template<class T, class Container = std::vector<T>>class priority_queue{private:void AdjustDown(int parent){size_t child = 2 * parent + 1;while (child < _con.size()){if (child + 1 < _con.size() && _con[child]<_con[child + 1]){child++;}if (_con[parent]< _con[child]){std::swap(_con[child], _con[parent]);parent = child;child = 2 * parent + 1;}else{break;}}}void AdjustUp(int child){int parent = (child - 1) / 2;while (parent >= 0){if (_con[parent]< _con[child]){std::swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}public:priority_queue(){}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);}}void push(const T& t){_con.push_back(t);AdjustUp(_con.size() - 1);}void pop(){std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}bool empty(){return _con.empty();}const T& top(){return _con[0];}size_t size(){return _con.size();}private:Container _con;};
}

此时,我们已经实现了一个大堆的优先级队列
那么怎么实现小堆的优先级队列呢?当前我们只能去修改向下调整和向上调整中比较大小的部分:
在这里插入图片描述

这其实挺麻烦的,有没有什么方法可以使大堆和小堆的优先级队列可以秒切换呢?
答案就是:可以使用仿函数



仿函数

仿函数也叫函数对象,这个类的对象可以像函数一样使用,使一个类的使用看上去像一个函数
其实现就是类中实现一个operator(),有了对括号的重载,就可以让这个类的对象像函数一样使用

下面就是一个仿函数:

class IntLess
{
public:bool operator()(int x,int y){return x < y;}};

怎么使用仿函数呢?毕竟仿函数是一个类,所以我们使用时需要先实例化一个对象出来
然后将这个对象像使用函数一样使用
在对象后面加上(),该传参就传参

void test2()
{IntLess LessFunc;cout<<LessFunc(1,2)<<endl;//仿函数的使用
}

LessFunc(1,2)会被处理成:LessFunc.operator()(1,2)

接下来,用仿函数完善模拟实现的优先级队列

template<class T>
struct Less//首字母大写,为了与库中的less区分
{bool operator()(const T& t1, const T& t2){return t1 < t2;}
};template<class T>
struct Greater
{bool operator()(const T& t1, const T& t2){return t1 > t2;}
};

首先,在模板声明中加一个参数:

template<class T,class Container = std::vector<T>,class Compare = Less<T>>

然后,然后将向上调整和向下调整中大小判断部分改为仿函数

void AdjustDown(int parent)
{Compare com;//仿函数使用前,实例化出一个对象size_t child = 2 * parent + 1;while (child < _con.size()){if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){child++;}if (com(_con[parent], _con[child])){std::swap(_con[child], _con[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}void AdjustUp(int child)
{Compare com;//仿函数使用前,实例化出一个对象int parent = (child - 1) / 2;while (parent >= 0){if (com(_con[parent], _con[child])){std::swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}

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

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

相关文章

Apollo在Java中的使用

本节主要讲解在普通的 Java 项目和 Spring Boot 中如何使用 Apollo。 普通 Java 项目中使用 加入 Apollo Client 的 Maven 依赖&#xff0c;代码如下所示。 <dependency><groupId>com.ctrip.framework.apollo</groupId><artifactId>apollo-client<…

kali 安装cpolar内网穿透实现 ssh 远程连接

文章目录 1. 启动kali ssh 服务2. kali 安装cpolar 内网穿透3. 配置kali ssh公网地址4. 远程连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 简单几步通过cpolar 内网穿透软件实现ssh 远程连接kali! 1. 启动kali ssh 服务 默认新安装的kali系统会关闭ssh 连接服务,我们通…

【3】单着色器文件读取

Basic.shader文件&#xff0c;可以发现顶点着色器和片段着色器是写在一个文件里的&#xff0c;这里我们将他们读取出来&#xff0c;而不是上一篇使用string的方式。 #shader vertex #version 330 corelayout(location 0) in vec4 position;void main() {gl_Position positio…

TTransportException SASL authentication not complete

今天遇见了一个异常&#xff0c;但是发现是自己智障了 但还是记录一下 在close的时候先close了conn再close的statement导致报的这个错

概念解析 | 无线智能空口:打造下一代无线通讯网络的关键技术

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:无线智能空口。 无线智能空口:打造下一代无线通讯网络的关键技术 前序 “空口"是无线通信中的一个专业术语,它主要用于描述无线通信设备与设备之间的通信接口。我们可…

Level-based Foraging 多智能体游戏仿真环境

游戏场景测试 参考链接&#xff1a; https://kgithub.com/semitable/lb-foraging

CNN详细讲解

CNN(Convolutional Neural Network) 本文主要来讲解卷积神经网络。所讲解的思路借鉴的是李宏毅老师的课程。 CNN&#xff0c;它是专门被用在影像上的。 Image Classification 我们从影像分类开始说起。 我们举例来说&#xff0c;它固定的输入大小是100*100的解析度&#x…

FastAPI 参数的作用

FastAPI是一个现代化的Python web框架&#xff0c;其参数具有重要的作用。在FastAPI中&#xff0c;参数被用于接收HTTP请求中的数据及其它相关信息。 FastAPI支持的参数类型包括&#xff1a; 查询参数&#xff08;query parameters&#xff09; 查询参数是指将参数附加到URL末…

《Python魔法大冒险》007 被困的精灵:数据类型的解救

小鱼和魔法师深入魔法森林&#xff0c;树木之间流淌着神秘的光芒&#xff0c;每一片叶子都似乎在低语着古老的咒语。不久&#xff0c;他们来到了一个小湖旁&#xff0c;湖中央有一个小岛&#xff0c;岛上困着一个透明的泡泡&#xff0c;里面有一个悲伤的精灵。 小鱼看着那个精…

软件行业25年技术发展史

语言时代 -> 框架时代 -> 分布式架构时代 -> 微服务架构时代 25年开发、管理&#xff0c;11年教培&#xff08;教研总监&#xff09;技术总结&#xff1a; 1997年 VB 1999年 ASPCOM 2004年 C# / JAVA、j2ee、ejb、struts1hibernate 2008年 旧三大框架 Struts2Spr…

MySQL 是如何实现事务的四大特性的?

分析&回答 如果你不知道事务更不知道四大特性请先看看&#xff1a;说说什么是事务 原子性 语句要么都执行&#xff0c;要么都不执行&#xff0c;是事务最核心的特性&#xff0c;事务本身来说就是以原子性来定义的&#xff0c;实现主要是基于undo log undo log&#xff…

探索ClickHouse——安装和测试

我们在Ubuntu 20 Server版虚拟机上对ClickHouse进行探索。 安装 检测环境 grep -q sse4_2 /proc/cpuinfo && echo "SSE 4.2 supported" || echo "SSE 4.2 not supported"SSE 4.2 supported 可以看到我们的环境支持编译版本的。如果不支持的环境…

MyBatisPlus之DQL编程控制

&#x1f40c;个人主页&#xff1a; &#x1f40c; 叶落闲庭 &#x1f4a8;我的专栏&#xff1a;&#x1f4a8; c语言 数据结构 javaEE 操作系统 石可破也&#xff0c;而不可夺坚&#xff1b;丹可磨也&#xff0c;而不可夺赤。 MyBatisPlus之DQL编程控制 一、 条件查询方式&…

zabbix安装部署

前期准备&#xff1a;安装mysql数据库和nginx 一、下载zabbix rpm -Uvh https://repo.zabbix.com/zabbix/4.4/rhel/7/x86_64/zabbix-release-4.4-1.el7.noarch.rpm yum-config-manager --enable rhel-7-server-optional-rpms yum install epel-release numactl yum install…

【LeetCode-面试经典150题-day21】

目录 120.三角形最小路径和 64.最小路径和 63.不同路径Ⅱ 5.最长回文子串 120.三角形最小路径和 题意&#xff1a; 给定一个三角形 triangle &#xff0c;找出自顶向下的最小路径和。 每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标…

JS 实现同时往数组多个位置插入值和删除值

1 start下标实现往固定地方插入数据 const aa [1, 2, 3, 4, 5, 6]; let bb [{ start: 5, list: [b1, b2, b3] },{ start: 0, list: [a1, a2] },{ start: 1, list: [c1, c2] },{ start: 1, list: [c11, c22] },{ start: 2, list: [d1, d2] },{ start: 3, deleteCount: 1 }, …

Python项目打包与部署(一):模块与包的概念与关系

当前各类Python教程鲜有涉及Python打包与部署技术&#xff0c;或者讲述过于表面化、片面化。 本人尝试从原理开始&#xff0c;结合实例&#xff0c;并给出标准操作步骤建议&#xff0c;为python编程爱好者提供一份较为详实的Python项目打包与部署参考教程。 本教程其它章节 Pyt…

SQL-存储过程、流程控制、游标

存储过程 存储过程概述 1.产生背景 开发过程总&#xff0c;经常会遇到重复使用某一功能的情况 2.解决办法 MySQL引人了存储过程(Stored Procedure)这一技术 3.存储过程 存储过程就是一条或多条SQL语句的集合存储过程可将一系列复杂操作封装成一个代码块&#xff0c;以便…

【【萌新的STM32的学习--非正点原子视频的中断设计思路】】

萌新的STM32学习–非正点原子视频的中断设计思路 我们分析而言 我们对于PA0 的设计就从此而来 对于边沿触发的选择我们已经有所了解了 我们下拉&#xff0c;但是当我们摁下开关的时候 从0到1 导通了 所以这个是下拉 上升沿触发 而对于KEY0 我们摁下是使得电路从原来悬空高阻态…

算法通关村第10关【黄金】| 归并排序

归并排序&#xff08;Merge Sort&#xff09;是一种常见的基于比较的排序算法&#xff0c;它的主要思想是分而治之&#xff08;Divide and Conquer&#xff09;。它的核心思想是将一个大的问题分解为小的子问题&#xff0c;解决子问题&#xff0c;然后将它们合并&#xff08;me…