零.前言
学习自卡尔老师,哔哩哔哩在这啦:
优先级队列正式登场!大顶堆、小顶堆该怎么用?| LeetCode:347.前 K 个高频元素_哔哩哔哩_bilibili
blog推荐
【C++】优先队列(Priority Queue)全知道_c++优先队列-优快云博客
一.Priority Queue怎么理解
优先队列就行ICU病房一样,并不是像普通的队列遵循先来后到的原则,就像ICU并非会根据病人生病的严重程度优先安排医疗一样,体现在优先队列中就是按照某个重要性的标准来进行排列。
二.优先队列是实现原理
堆是一种特殊的完全二叉树结构,有大根堆和小根堆之分:
- 大根堆:每个节点的值都大于或等于其子节点的值,这意味着堆顶元素是整个堆中的最大值。
- 小根堆:每个节点的值都小于或等于其子节点的值,所以堆顶元素是整个堆中的最小值。
大根堆实现逻辑
从整棵树的最后一颗子树开始调整,每次都让根节点和左右孩子去比较,如果根节点比左右孩子的最大值要小,那么就将这两个值进行交换,然后此时这颗子树变成了大根堆,再看下一颗树
然后对下一颗树进行相同的处理方法,后面的子树依次交换:
当每棵子树都是大根堆的情况下,那么这棵树也就是大根堆了
小根堆同理
三.优先队列的使用
四.求解出现频率最高的前k个元素
4.1题目描述
4.2我的思路图解:
4.3Coding:
#include<bits/stdc++.h>
using namespace std;
class mycomparision
{
public:
bool operator()(pair<int,int> l,pair<int,int> r)
{
return l.second > r.second;
}
};
vector<int> kTopElement(const vector<int>& v,int k)
{
//count the frequence of vector element and put the number into map
unordered_map<int,int> m;
for(const auto& it:v)
{
m[it]++;
}
//use minHeap to count the nost frequent element of map
priority_queue<pair<int,int>,vector<pair<int,int>>,mycomparision> prior_que;
int i = 0;
for(const auto& comb : m)
{
prior_que.push(comb);
if(prior_que.size() > k)
{
prior_que.pop();
}
}
//use vector to load the element of priority queue
vector<int> result;
while(!prior_que.empty())
{
result.push_back(prior_que.top().first);
prior_que.pop();
}
return result;
}
int main()
{
vector<int> v{2,1,1,2,3,2,4,4,4,4,5,6,12};
int k = 3;
vector<int> result = kTopElement(v,k);
reverse(result.begin(),result.end());
for(const auto& it : result)
{
cout << it << " ";
}
return 0;
}