当前位置: 首页 > news >正文

暴力数据结构之优先级队列的解析及其模拟实现(C++)

1.认识优先级队列

如果我们给每个元素都分配一个数字来标记其优先级,不妨设较小的数字具有较高的优先级,这样我们就可以在一个集合中访问优先级最高的元素并对其进行查找和删除操作了。

优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有(1)查找(2)插入一个新元素 (3)删除

一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行

在默认情况下优先级最高的通常是队列中最大的数字,当然我们也可以只用仿函数来更改其队列中元素的优先级,优先级队列的底层实质上就是堆,也就是数组

2.模拟实现优先级队列

首先回顾一下完全二叉树中父节点与左右子结点的关系:left child = parent * 2 + 1; right child = parent * 2 + 2; parent = (child - 1) / 2

namespace bit
{template<class T,class Container = vector<T>>class priority_queue{public://向上调整void AdjustUp(size_t child){size_t parent = (child - 1) / 2;while (child > 0){//将大的值移向堆顶,建大堆if (_con[parent] < _con[child]){swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}//向下调整void AdjustDown(size_t parent){//假设为左子结点size_t child = parent * 2 + 1;while (child > 0){//找到大的子结点 if (child + 1 < _con.size() && _con[child] < _con[child + 1]){child++;}if (_con[child] > _con[parent]){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void push(const T& x){_con.push_back(x);//从堆底向上调整AdjustUp(_con.size() - 1);}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();//从堆顶向下调整AdjustDown(0);}const T& top(){return _con[0];}size_t size(){return _con.size();}bool empty(){return _con.empty();}private:Container _con;};
}

3.仿函数 

首先我们要知道仿函数的本质是一个类,为了使代码更加具有灵活性,我们就使用到了仿函数来重载 operator(),以达到改变大/小堆的功能

template<class T>
class Less
{
public:bool operator()(const T& x, const T& y){return x < y;}
};template<class T>
class Greater
{
public:bool operator()(const T& x, const T& y){return x > y;}
};
namespace bit
{//默认是大堆template<class T,class Container = vector<T>,class Compare = Less<T>>class priority_queue{public://向上调整void AdjustUp(size_t child){Compare com;size_t parent = (child - 1) / 2;while (child > 0){//将大的值移向堆顶,建大堆//if (_con[child] < _con[parent])if (com(_con[child],_con[parent])){swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}//向下调整void AdjustDown(size_t parent){Compare com;//假设为左子结点size_t child = parent * 2 + 1;while (child > 0){//找到大的子结点 //if (child + 1 < _con.size() && _con[child] < _con[child + 1])if (child + 1 < _con.size() && com(_con[child],_con[child + 1])){child++;}//if (_con[parent]<_con[child])if (com(_con[parent],_con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void push(const T& x){_con.push_back(x);//从堆底向上调整AdjustUp(_con.size() - 1);}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();//从堆顶向下调整AdjustDown(0);}const T& top(){return _con[0];}size_t size(){return _con.size();}bool empty(){return _con.empty();}private:Container _con;};
}

4.实战代码练习 

LCR076.数组中的第K个最大元素,本题使用优先级队列可以很简单的解决问题

class Solution {
public:int findKthLargest(vector<int>& nums, int k) {//将元素存储到优先级队列priority_queue<int> pq;for(auto& e : nums){pq.push(e);}//取出前k-1个最大元素,剩下的元素中最大的元素就是第k个最大元素for(int i = 0;i < k - 1;i++){pq.pop();}return pq.top();}
};

 


http://www.mrgr.cn/news/21142.html

相关文章:

  • ECMAScript与JavaScript的区别:深入解析与代码示例
  • QT项目实战之音乐播放器2.0版本
  • 论文阅读 - Coordinated Activity Modulates the Behavior and Emotions ofOrganic Users
  • 技术速递|从 .NET 9 中移除 BinaryFormatter
  • 初识string(一)and内存管理
  • 【网络安全 | 甲方建设】SaaS平台、Jira工具及Jenkins服务器
  • 使用“天聚数行”藏头诗生成API:轻松创作个性化诗词
  • 江协科技STM32学习- P11 中断系统,EXTI外部中断
  • 使用cage工具包生成验证码
  • RP2040 C SDK clocks时钟源配置使用
  • 嵌入式s3c2240: ADC
  • Flutter集成Firebase中的Realtime Analytics
  • C#读写锁与并发控制
  • 电脑桌面整理怎么弄?分享8款桌面整理软件,轻松拿捏桌面美化!
  • 【脚手架 第一篇章】介绍一下若依微服务版框架
  • 超级兔子与这三款恢复工具:性能对比与用户体验分析
  • 数学基础 -- 线性代数之矩阵正定性
  • 10款古方突破1800亿元,康缘药业发力,市场迎井喷式增长……
  • 2024.9.6 作业
  • 【简历】25届南京某一本JAVA简历:简历通过率还好,但是拿不到OFFER