【priority_queue】【make_heap/push_heap/pop_heap】的用法及参数解析

1. 前言

主要分为两部分
1.priority_queue的作用: 实现 大顶堆小顶堆,本文主要就该容器的使用方法和如何定义第三个模板参数进行详解,需要读者对模板、函数指针、函数对象(仿函数)有一定了解,当然也有对函数指针和函数对象的区别作简单介绍
2. 第二种库函数方法实现大小顶堆:vector、make_heap、push_heap、pop_heap组合使用,
·

2.1 priority_queue函数原型解析

template<class _Ty,
	class _Container = vector<_Ty>,
	class _Pr = less<typename _Container::value_type> >
	class priority_queue

这是priority_queue的底层代码,如是指定第一个参数的类型,后面两个模板参数都会有默认形式,如,priority_queue<int>,第二个模板参数默认取vector<int>类型,第三个默认取less<int>类型(less底层是一个结构体)。然而本文重点是第三个参数的制定。

2.2 priority_queue的使用方法介绍

priority_queue和队列基本操作相同:关于怎么操作请参考,不是本文重点。

top 访问队头元素
empty 队列是否为空
size 返回队列内元素个数
push 插入元素到队尾 (并排序)
emplace 原地构造一个元素并插入队列
pop 弹出队头元素
swap 交换内容

创建priority_queue的三种不同方式:
1.第一种:只定义一个参数,默认形式下,这里是一个关于字符串的大顶堆(按字符串的第一个字符排,最大的在堆顶)

priority_queue<string> pq;//也可以是 int,char等

2.第二种:改变第三个模板参数实现小顶堆解析,需要注意的是,为什么这里不是sort(v.begin(),v.end(),less<int>())那样调用函数对象 加括号() 呢:因为sort这里第三个参数是是传实参,为函数对象或者函数指针,这里的less<int>()是一个函数对象,less结构体的operator()函数。而priority_queue在创建的时候是指定模板参数,也就是指定参数的类型,所以是使用less<int>,告诉priority_queue第三个模板的参数类型是一个less<int>类,不加()。函数对象其实也是一种函数指针,但是两者之间的区别我有作简单的介绍,足够理解本文。

priority_queue<int,vector<int>,less<int>> pq;

·
3. 第三种:当第一个模板参数是自定义数据时,就需要自定义一个比较方式,可以是一个比较(需要重载(),以调用函数对象),可以是一个函数指针(一般采用lamda表达式,因为它需要使用当前函数的传入参数,但又不能在函数体内定义函数,故采用这样的方式)。
1)采用作为第三个模板参数。指定第三个模板参数是cmp类型,不能是cmp()函数对象(仿函数)。

struct Node{//也可以是class
	int x,y;
	Node(int a=0, int b=0):
		x(a), y(b) {}
};
 
struct cmp{//也可以是class
	bool operator()(Node a, Node b){
		if(a.x == b.x)	return a.y>b.y;
		return a.x>b.x;  //>实现小顶堆,<实现大顶堆
	}
};

int main(){
	priority_queue<Node, vector<Node>, cmp>p;
	
	for(int i=0; i<10; ++i)
		p.push(Node(rand(), rand()));
		
	while(!p.empty()){
		cout<<p.top().x<<' '<<p.top().y<<endl;
		p.pop();
	}//while
	//getchar();
	return 0;
}

·
·
2)采用函数指针作为第三个模板参数。这里以leetcode剑指offerII 061的题解代码为例,实现第三个参数为函数指针priority_queue。而这里采用lamda表达式,因为它需要用到kSmallestPairs的参数,而不写在函数体外。然后重点来了,需要结合decltype(cmp)pq(cmp)的使用方式(具体原理不清楚)。个人理解是声明cmp函数(实际是以指针)为一个指针类,从而作为模板参数,并在命名的时候使用pq(cmp),把函数指针cmp作为参数初始化pq。
同时说明cmp在>下实现小顶堆,<实现大顶堆,理解就是后面来的数据在符号右边,如>,它小就返回true,让后面进来的数和前面的数换位置,实现小顶堆。

 vector<vector<int>> kSmallestPairs(vector<int>& nums1, vector<int>& nums2, int k){
  auto cmp=[&](const pair<int, int>& lhs, const pair<int, int>& rhs){
            return nums1[lhs.first] + nums2[lhs.second] > nums1[rhs.first] + nums2[rhs.second];
//当后面进来下标pair对rhs下:nums1[rhs.first] + nums2[rhs.second]小时,将这个rhs和lhs置换,实现小顶堆
        };
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp)> pq(cmp);
}

2.3 总结

如果还是不理解可以结合下面几篇高访文章理解,或留言评论区,当然我也是初出茅庐,如有不对之处还望请大佬指出。
https://blog.csdn.net/weixin_36888577/article/details/79937886
[https://blog.csdn.net/xiaoquantouer/article/details/52015928?]


3.1 make_heap等组合实现大小顶堆的方法

vectormake_heappush_heappop_heap的各功能如代码里面的注释所示
大顶堆的实现:第三个参数默认是less<int>() 函数对象

#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int main(int argc, char const *argv[]) {
    int myints[] = {10,20,30,5,15};     // fixed-size array
    vector<int> v(myints, myints+5);    // convert to vector
    make_heap(v.begin(), v.end());      // make max heap from range
    cout << "initial max heap   : " << v.front() << "\n";  // heap top
    
    pop_heap(v.begin(), v.end());       // move heap top to the end
    v.pop_back();                       // pop/remove back the last element
    cout << "max heap after pop : " << v.front() << "\n";

    v.push_back(99);                    // insert an element to the end
    push_heap(v.begin(), v.end());      // rearrange elements to form a heap
    cout << "max heap after push: " << v.front() << "\n";
    
    cout << "max heap range     :";
    for (int i = 0; i < v.size(); i++) {
        cout << " " << v[i];
    }
    cout << "\n";
    return 0;
}

大顶堆的结果为:

initial max heap   : 30
max heap after pop : 20
max heap after push: 99
max heap range     : 99 20 10 5 15

··········································································································································································
实现小顶堆:更改第三个参数为greater<int>()

//make_heap组合使用实现小顶堆
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

int main() {
	int myints[] = { 10,20,30,5,15 };     // fixed-size array
	vector<int> v(myints, myints + 5);    // convert to vector
	make_heap(v.begin(), v.end(),greater<int>());      // make min heap from range
	cout << "min heap range     :";
	for (int i = 0; i < v.size(); i++) {
		cout << " " << v[i];
	}cout << "\n";
	cout << "initial min heap   : " << v.front() << "\n";  // heap top

	pop_heap(v.begin(), v.end(), greater<int>());       // move heap top to the end,and make min heap from range except the last element
	cout << "min heap range after pop_heap:";
	for (int i = 0; i < v.size(); i++) {
		cout << " " << v[i];
	}cout << "\n";
	
	v.pop_back();                       // pop/remove back the last element
	cout << "min heap after pop : " << v.front() << "\n";

	v.push_back(99);                    // insert an element to the end
	push_heap(v.begin(), v.end());      // rearrange elements to form a heap
	cout << "min heap after push: " << v.front() << "\n";

	cout << "min heap range     :";
	for (int i = 0; i < v.size(); i++) {
		cout << " " << v[i];
	}cout << "\n";
	

	system("pause");
	return 0;
}

大顶堆结果为:

min heap range     : 5 10 30 20 15
initial min heap   : 5
min heap range after pop_heap: 10 15 30 20 5
min heap after pop : 10
min heap after push: 99
min heap range     : 99 10 30 20 15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值