c++中的堆-priority_queue的使用方法

堆作为一个重要的数据结构,应该是接触编程的人员都会了解的,本文是在写leetcode中,由于需要经常使用到堆这一数据结构而写的学习记录帖。即使手撸一个堆并不复杂,但是还是大大拖慢的写题节奏,更何况自己写的堆无论是效率还是安全性咱也没什么信息,这就是STL各个模板发挥的时候了。这里就来简单介绍一下priority_queue,即优先队列。

1 priority_queue的底层实现

PriorityQueue中的元素在逻辑上构成了一棵完全二叉树,但实际这个堆结构在物理存储上是用数组实现的。如果有兴趣了解,可以看看这个博客

2 priority_queue基本操作

2.1 已有数据类型初始化

小根堆初始化
priority_queue<int,vector<int>,greater<int>> p
大根对初始化
priority_queue<int,vector<int>,less<int>> p
三个参数的意思:

/*
@para p1 :该队列盛放的数据类型
@para p2 :container,需要是数组实现,一般就是vector
@para p3 :比较器,(因为涉及到了比较排序嘛
*/

一般如果我们要使用大根堆且不用自定义的数据结构,只要填写第一个参数即可:
priority_queue<int> p
对于一些已由的数据类型,我们就免去了定义比较器的麻烦,直接使用greater<>less<>即可。值得注意的是,对于tuplepair这样的结构,也已经定义好了比较器:

  1. pair举例
//默认是使用大根堆
priority_queue<pair<int,int>> pq0;
//小根堆,按照pair的first排,再按照second排序
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> pq1;
//大根堆
priority_queue<pair<int,int>,vector<pair<int,int>>,less<pair<int,int>>> pq2;
  1. tuple举例
//默认是使用大根堆
priority_queue<tuple<int,int,int>> tp0;
//小根堆,按照tuple的0元素排,再按照1元素排,最后按2元素排
priority_queue<tuple<int,int,int>,vector<tuple<int,int,int>>,greater<tuple<int,int,int>>> tp1;
//大根堆
priority_queue<tuple<int,int,int>,vector<tuple<int,int,int>>,less<tuple<int,int,int>>> tp2;

2.2 自定义数据结构的堆

但是自定义数据结构可以让我们更加自由的编程,所以是必须要探讨的。下面这段程序,我写出了当自定义struct后,我们该如何初始化优先队列。

  1. 重载<符号
  2. 写一个比较器
    (两者实现一个即可)
#include <iostream>
#include <queue>
using namespace std;
struct node{
    int sum;
    int x;
    int y;
    node(){};
    node(int a,int b,int c){
        sum=a;
        x=b;
        y=c;
    }
    //一定要加const
    friend bool operator < (const node& a, const node&b){
        //构建一个大根堆,因为默认是大根堆,而定义的小于符合本意的小于
        return a.sum<b.sum;
        //如果反着来的话,就是小根堆
    }
};
//使用比较器来构建小根堆
class cmp{
public:
    bool operator () (const node&a,const node &b){
        return a.sum<b.sum;
    }
};
int main() {
    priority_queue<node> tp;
    // priority_queue<node,vector<node>,cmp> tp;//使用比较器版本
    for(int i=0;i<10;i++){
        tp.push(node(i,1,2));
    }

    while(!tp.empty()){
        cout<<tp.top().sum<<endl;
        tp.pop();
    }
    return 0;
}

2.3 基本操作(和queue相似操作)

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

3 堆的使用场景

这个其实还蛮多的,做题时大概有个感觉:当我们需要不断对数据排序的同时,还需要进行更新,并且只关注局部数据时,堆就是比较好的选择,比如经典的求前K个最大的等等太多了。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值