C++优先队列——priority_queue,函数对象,labmda表达式,pair等

2024-03-29 07:04

本文主要是介绍C++优先队列——priority_queue,函数对象,labmda表达式,pair等,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

头文件:#include<queue>

内部使用堆来实现,在需要或得最大的几个值或最小的几个值而不关心整个数组的顺序时非常好用。

用法:

priority_queue<int, vector<int>, greater<int>>q;
第一个参数为堆中存储的元素。

第二个参数为底层使用的存储结构,默认使用vector。

第三个参数为优先队列中元素的比较方式的类。如果是小根堆则为greater,大根堆为less;less、greater二者为仿函数,即把类当作函数使用,本质上为类,内部重载了()运算符,所以可以当作函数。

如果堆中存储的是int元素,则只需要传入less或greater即可,less<T>来定义大顶堆,
greater<T>来定义小顶堆,不需要我们手动实现。

如果传入的是其他复杂类型,则需要我们手动实现比较类。

参考下面这篇文章:

http://t.csdnimg.cn/04qeZ

lambda表达式的详细信息可参考下面这篇:http://t.csdnimg.cn/42OXw

刷题时遇到一道题,

给定两个以 非递减顺序排列 的整数数组 nums1 和 nums2 , 以及一个整数 k 

定义一对值 (u,v),其中第一个元素来自 nums1,第二个元素来自 nums2 

请找到和最小的 k 个数对 (u1,v1) (u2,v2)  ...  (uk,vk) 。

暂未想到合适的解决方案,刚好这题在堆这一章里面,于是考虑使用堆实现。

class cmp
{
public:bool operator()(pair<int,int>&p1,pair<int,int>&p2){return p1.first+p1.second<p2.first+p2.second;}
};class Solution {
public:vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {priority_queue<pair<int,int>,vector<pair<int,int>>,cmp>q;vector<vector<int>>res;for(int i=0;i<nums1.size();i++){for(int j=0;j<nums2.size();j++){if(q.size()<k)q.push(make_pair(nums1[i],nums2[j]));else if(nums1[i]+nums2[j]<q.top().first+q.top().second){q.pop();q.push(make_pair(nums1[i],nums2[j]));}}}while(k--){vector<int>temp;temp.push_back(q.top().first);temp.push_back(q.top().second);res.push_back(temp);q.pop();}return res;}
};

大顶堆小顶堆巧记:在cmp判断函数中,总是返回右边的,即p2。如果是>,则右边较小,为小顶堆。如果是<,则右边较大,为大顶堆。

上述代码中就是使用了大顶堆,大顶堆的数量不超过k,当来了一个新的元素对,将该元素对之和与堆顶元素之和作比较,如果小于堆顶元素之和,说明堆顶还不是最小的k个之一,将堆顶弹出,插入当前元素对。

注:关于pair:函数定义时参数使用pair<int, int>& p1。使用p1.first , p1.second来获取其中的元素。使用pair<int,int>p=make_pair(q.top().first,q.top().second);,也可以直接将make_pair传入函数参数中。

虽然最后只通过了20/30的测试用例,但在数据量较小时也不失为一种方法,且对priority_queue以及函数对象、lambda表达式有了更深刻的认识。

也可以使用lambda表达式:

        auto cmp=[](pair<int,int>&p1,pair<int,int>&p2){return p1.first+p1.second<p2.first+p2.second;};priority_queue<pair<int,int>,vector<pair<int,int>>,decltype(cmp)>q(cmp);

上述题目正解:

class Solution {
public:vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k) {auto cmp = [&nums1, &nums2](const pair<int, int> & a, const pair<int, int> & b) {return nums1[a.first] + nums2[a.second] > nums1[b.first] + nums2[b.second];};int m = nums1.size();int n = nums2.size();vector<vector<int>> ans;   priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> pq(cmp);for (int i = 0; i < min(k, m); i++) {pq.emplace(i, 0);}while (k-- > 0 && !pq.empty()) {auto [x, y] = pq.top(); pq.pop();ans.emplace_back(initializer_list<int>{nums1[x], nums2[y]});if (y + 1 < n) {pq.emplace(x, y + 1);}}return ans;}
};

整体思路相似,都是使用堆。不过该程序堆存储的是数组的索引,便于获得后面索引的值。

在一开始时将0,0  1,0  2,0  3,0......i,0加入堆。每次出堆时,仅仅将i,j+1入堆(事实上i,j入堆下一个可能最小的是i+1,j或i,j+1,但是如果二者都入堆有可能出现重复,即i+1,j+1重复入堆。所以一开始将0,j全部入堆,每次出堆时仅将i,j+1入堆即可,直到结果集中有k个元素。)

这篇关于C++优先队列——priority_queue,函数对象,labmda表达式,pair等的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/857924

相关文章

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指

Python中判断对象是否为空的方法

《Python中判断对象是否为空的方法》在Python开发中,判断对象是否为“空”是高频操作,但看似简单的需求却暗藏玄机,从None到空容器,从零值到自定义对象的“假值”状态,不同场景下的“空”需要精... 目录一、python中的“空”值体系二、精准判定方法对比三、常见误区解析四、进阶处理技巧五、性能优化

C++中初始化二维数组的几种常见方法

《C++中初始化二维数组的几种常见方法》本文详细介绍了在C++中初始化二维数组的不同方式,包括静态初始化、循环、全部为零、部分初始化、std::array和std::vector,以及std::vec... 目录1. 静态初始化2. 使用循环初始化3. 全部初始化为零4. 部分初始化5. 使用 std::a

shell编程之函数与数组的使用详解

《shell编程之函数与数组的使用详解》:本文主要介绍shell编程之函数与数组的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录shell函数函数的用法俩个数求和系统资源监控并报警函数函数变量的作用范围函数的参数递归函数shell数组获取数组的长度读取某下的

MySQL高级查询之JOIN、子查询、窗口函数实际案例

《MySQL高级查询之JOIN、子查询、窗口函数实际案例》:本文主要介绍MySQL高级查询之JOIN、子查询、窗口函数实际案例的相关资料,JOIN用于多表关联查询,子查询用于数据筛选和过滤,窗口函... 目录前言1. JOIN(连接查询)1.1 内连接(INNER JOIN)1.2 左连接(LEFT JOI

SpringKafka错误处理(重试机制与死信队列)

《SpringKafka错误处理(重试机制与死信队列)》SpringKafka提供了全面的错误处理机制,通过灵活的重试策略和死信队列处理,下面就来介绍一下,具有一定的参考价值,感兴趣的可以了解一下... 目录引言一、Spring Kafka错误处理基础二、配置重试机制三、死信队列实现四、特定异常的处理策略五

C++ vector的常见用法超详细讲解

《C++vector的常见用法超详细讲解》:本文主要介绍C++vector的常见用法,包括C++中vector容器的定义、初始化方法、访问元素、常用函数及其时间复杂度,通过代码介绍的非常详细,... 目录1、vector的定义2、vector常用初始化方法1、使编程用花括号直接赋值2、使用圆括号赋值3、ve

MySQL中FIND_IN_SET函数与INSTR函数用法解析

《MySQL中FIND_IN_SET函数与INSTR函数用法解析》:本文主要介绍MySQL中FIND_IN_SET函数与INSTR函数用法解析,本文通过实例代码给大家介绍的非常详细,感兴趣的朋友一... 目录一、功能定义与语法1、FIND_IN_SET函数2、INSTR函数二、本质区别对比三、实际场景案例分

如何高效移除C++关联容器中的元素

《如何高效移除C++关联容器中的元素》关联容器和顺序容器有着很大不同,关联容器中的元素是按照关键字来保存和访问的,而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的,本文介绍了如何高效移除C+... 目录一、简介二、移除给定位置的元素三、移除与特定键值等价的元素四、移除满足特android定条件的元

Python获取C++中返回的char*字段的两种思路

《Python获取C++中返回的char*字段的两种思路》有时候需要获取C++函数中返回来的不定长的char*字符串,本文小编为大家找到了两种解决问题的思路,感兴趣的小伙伴可以跟随小编一起学习一下... 有时候需要获取C++函数中返回来的不定长的char*字符串,目前我找到两种解决问题的思路,具体实现如下: