priority_queue(堆)干货归纳+用法示例

Posted LiuZuqiang_3027

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了priority_queue(堆)干货归纳+用法示例相关的知识,希望对你有一定的参考价值。

10.priority_queue

一.priority_queue(堆Heap)简介

在C++中,堆(Heap)是一种特殊的树状数据结构,其中每个节点都比其子节点大或小(具体取决于堆的类型)。堆通常用于实现优先队列和排序算法。

1.堆的特点:

  1. 完全二叉树:堆是一种完全二叉树,即除了最后一层节点可以不满外,其它层节点都必须满足。
  2. 有序性:堆中的每个节点都比其子节点大或小(具体取决于堆的类型),满足堆的有序性。
  3. 快速插入和删除:由于堆的特殊结构,可以在O(log n)的时间复杂度内进行插入和删除操作。

C++中有两种类型的堆:最大堆(Max Heap)和最小堆(Min Heap)。最大堆的每个节点都比其子节点大,而最小堆的每个节点都比其子节点小。通常使用头文件中的priority_queue类来实现堆。

priority_queue类特点:

  • 自动排序:priority_queue会自动按照元素的大小进行排序,因此每次取出的元素都是当前最大(或最小)的元素。
  • 高效的插入和删除操作:priority_queue使用堆的数据结构,插入和删除元素的时间复杂度为O(log
    n),其中n是容器中的元素数量。
  • 支持随机访问:虽然priority_queue本身不支持随机访问,但是可以通过其底层的容器(默认是vector)来实现随机访问。

2.使用场景:

  1. 找到数组或序列中的第K大或第K小元素;
  2. 求一组数据的中位数;
  3. 排序算法,如堆排序、选择排序等;
  4. 优先队列,如Dijkstra算法、Prim算法等。

priority_queue的使用场景:

  • 求Top K元素:如果需要求一个序列中最大(或最小)的K个元素,可以使用priority_queue。
  • 任务调度:如果有多个任务需要按照优先级进行执行,可以将任务按照优先级放入priority_queue中,每次从队列中取出优先级最高的任务进行执行。
  • Dijkstra算法:Dijkstra算法是求解单源最短路径的经典算法之一,其中需要使用priority_queue来维护当前距离起点最短的点

二.成员函数

1.构造函数:priority_queue构造函数方式:

  • 默认构造函数:创建一个空的priority_queue(默认使用std::less函数对象来进行排序,也就是说它是一个大根堆,将最大值放在队首)。
priority_queue<int> q;  // 创建一个空的priority_queue
  • 带参构造函数:创建一个priority_queue,并将参数中的元素放入其中。
priority_queue<int> q(1, 2, 3, 4);  // 创建一个priority_queue,并将元素1、2、3、4放入其中
  • 自定义比较函数的构造函数:可以通过自定义比较函数来指定priority_queue的排序方式。
auto cmp = [](int a, int b)  return a > b; ;
priority_queue<int, vector<int>, decltype(cmp)> q(cmp);  // 创建一个priority_queue,使用自定义的比较函数

2.push()函数:向priority_queue中插入一个元素:

q.push(10);  // 向priority_queue中插入元素10

3.pop()函数:弹出priority_queue中的队首元素:

q.pop();  // 弹出priority_queue中的队首元素

4.top()函数:获取priority_queue中的队首元素:

int x = q.top();  // 获取priority_queue中的队首元素

5.size()函数:获取priority_queue中的元素个数:

int s = q.size();  // 获取priority_queue中的元素个数

6.empty()函数:判断priority_queue是否为空:

bool is_empty = q.empty();  // 判断priority_queue是否为空

三.程序示例

下是一个使用最大堆求一组数据的前K大元素的例子:

#include <iostream>
#include <vector>
#include <queue>
using namespace std;

vector<int> topk(vector<int>& nums, int k) 
    priority_queue<int, vector<int>, less<int>> pq; // 最大堆
    for (int num : nums) 
         pq.push(num);
    
    vector<int> result;
    while (!pq.empty() && result.size() <k ) 
        result.push_back(pq.top());
        pq.pop();
    
    return result;


int main() 
    vector<int> nums =  3, 2, 10, 5, 6, 4,3,7 ;
    int k = 2;
    vector<int> result = topk(nums, k);
    for (int num : result) 
        cout << num << " ";
    
    return 0;

该程序使用最大堆求一组数据的前K大元素,将数据依次插入堆中,如果堆的大小小于K,则直接插入;否则,将堆顶元素与当前元素比较,如果堆顶元素比当前元素小,则弹出堆顶元素并插入当前元素。最后,将堆中所有元素依次取出并返回即可。

C++ 优先队列 堆 priority_queue的使用 以及内部使用结构化pair的排序的用法 auto在其中的用法(结构化绑定 C++17以上)

C++ 优先队列 priority_queue的使用 以及内部使用结构化pair的排序的用法 auto在其中的用法(结构化绑定 C++17以上)

定义 初始化一个优先队列

//升序队列
priority_queue <int,vector<int>,greater<int> > q;
//降序队列
priority_queue <int,vector<int>,less<int> >q;

升序的使用pair的优先队列 默认对pair的第一个元素排序,所以建议数字放pair的第一个,用xx.first引用

//升序的使用pair的优先队列
priority_queue<pair<int, string>,vector<pair<int,string>>,greater<pair<int,string>> > pq;
//升序的使用pair的优先队列
priority_queue<pair<int, string>,vector<pair<int,string>>,less<pair<int,string>> > pq;

对pair结构体自定义排序

struct cmp
    template <typename T, typename U>
        bool operator()(T const &left, U const &right)
        
        // 以 second 比较。输出结果为 Second 较大的在前 Second 相同时,先进入队列的元素在前。 对pair第二个元素做降序排列 升序就反之
            return left.second > right.second;
        
    ;
    priority_queue<pair<int, int>, vector<pair<int, int>>, cmp> pq;

优先队列的API insert top erase都可以使用 下面介绍auto在其中的使用 只支持C++17以上

C++17结构化绑定 官方指南

假设我们有一个优先队列pq 我们要取队首 使用pq.top() 可以有两种写法

priority_queue<pair<int, string>,vector<pair<int,string>>,greater<pair<int,string>> > pq;
q.insert(make_pair(1,'a'));
q.insert(make_pair(2,'b'));

auto t1=q.top();
cout<<t1.first<<t1.second;//第一种

auto [num,name]=t1.top();//第二种 c++17以上

以上是关于priority_queue(堆)干货归纳+用法示例的主要内容,如果未能解决你的问题,请参考以下文章

C++ 优先队列 堆 priority_queue的使用 以及内部使用结构化pair的排序的用法 auto在其中的用法(结构化绑定 C++17以上)

C++ 优先队列 堆 priority_queue的使用 以及内部使用结构化pair的排序的用法 auto在其中的用法(结构化绑定 C++17以上)

priority_queue用法

priority_queue优先级队列总结

算法拾遗[4]——STL用法

c++优先队列(priority_queue)用法详解