模拟实现priority_queue

文章目录

  • priority_queue简介
  • priority_queue的实现
    • Myless和Mygreater
    • push
    • pop
    • 常规接口
  • 全部代码
    • 测试代码
  • 总结

在这里插入图片描述

priority_queue简介

在这里插入图片描述

priority_queue是优先级队列。
什么是优先级队列?
优先级队列(Priority Queue)是一种数据结构,用于管理一组元素,使得每个元素都有一个关联的优先级,并且元素按照优先级进行排序和访问。优先级队列常用于调度算法、图算法(如Dijkstra算法)、操作系统任务管理等场景。它的主要特点是可以快速地插入元素和找到具有最高优先级的元素。
简单来说优先级队列就是一个堆,在STL底层默认是大堆,堆顶的元素是堆里最大的,搞懂了优先级队列,其实大概得几个接口我们也知道了,就是插入和删除还有几个常规的判空之类的。
为了更好的实现优先级队列,我们先来做做铺垫,我们看官方文档给出的模版参数
在这里插入图片描述
前两个我们都很熟悉了,第一个就是普通的模版参数,第二个是容器适配器,第三个是我们接下来要介绍的,仿函数
什么事仿函数?

int main()
{Myless<int> l;l(1, 2);return 0;
}

看上面代码,如果单看上面的代码的话,如果不看类的实例化,这很容易让人误会这是在调用一个名字是l的函数,但是如果我们把上面这个类给写出来呢?

template<class T>
class Myless
{
public:bool operator()(const T& x, const T& y){return x < y;}
private:
};

其实这是一个重载了operator()的函数,这个函数的操作是由我们确定的,所以我们可以像调用函数一样,去调用类的成员函数。
仿函数概念:仿函数(Functor)也被称为函数对象(Function Object),是指一个可以像函数一样使用的对象。它是通过重载类的函数调用运算符operator()来实现的。仿函数在许多场景中都非常有用,例如在标准模板库(STL)中用于算法和容器。
我们通过控制仿函数的行为可以控制类中的比较的操作,也就是说,我们可以控制这个类到底是建小堆还是建大堆。

priority_queue的实现

Myless和Mygreater

由于我们要控制建大堆和建小堆,所以我们创建两个类,类的成员函数只有一个就是operator()用于控制优先级队列中的比较操作,当我们要建大堆的时候就调用Myless,这里在模版参数里,我们默认给的就是建大堆的Myless,如果大家还是不能理解的话接下来看了下面的代码,应该更能理解。
我们先将两个类定义出来:

template<class T>
class Myless
{
public:bool operator()(const T& x, const T& y){return x < y;}
};
template<class T>
class Mygreater
{
public:bool operator()(const T& x, const T& y){return x > y;}
};

模版参数:

template<class T, class Container = vector<int>, class Compare = Myless<T>>

push

由于优先级队列就类似于堆,所以和堆的操作类似,我们先将元素尾插,然后进行向上调整算法进行建堆操作

void push(const T& x)
{_con.push_back(x);Adjust_Up(_con.size() - 1);
}
void Adjust_Up(int child)
{Compare confunc;int parent = (child - 1) / 2;while (child > 0){if (confunc(_con[parent], _con[child])){std::swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}
}

pop

由于pop最后一个数据是没什么意义的,所以这里我们pop的是堆顶的数据,直接pop堆顶的数据,我们需要重新建堆付出的代价太大了,所以这里我们将收尾两个元素交换,然后直接pop队尾的数据,这样只有堆顶的数据是不符合堆的定义的,所以我们只需要向下调整即可。

const T& top()
{return _con.front();
}
void Adjust_Down(int parent)
{Compare confunc;int child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && confunc(_con[child], _con[child + 1])){child++;}//默认建大堆if (confunc(_con[parent], _con[child])){std::swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

在这里插入图片描述

在这里插入图片描述
可以看到在向上调整算法和向下调整算法中我们都用到了我们的仿函数,先创建一个对象,然后调用这个类的operator(),这个函数的行为就是去控制大于和小于,从而达到控制建小堆还是建大堆,如果是缺省参数,就直接建大堆,如果是调用Mygreater就建小堆。

常规接口

size_t size()
{return _con.size();
}
const T& top()
{return _con.front();
}
bool empty()
{return _con.empty();
}

全部代码

namespace lyrics
{template<class T>class Myless{public:bool operator()(const T& x, const T& y){return x < y;}};template<class T>class Mygreater{public:bool operator()(const T& x, const T& y){return x > y;}};template<class T, class Container = vector<int>, class Compare = Myless<T>>class priority_queue{public:priority_queue() = default;template<class InputIterator>priority_queue(InputIterator first, InputIterator last){while (first != last){_con.push_back(*first);first++;}//从最下面的第一个非叶子节点开始调整for (int i = (_con.size() - 1 - 1) / 2;i >= 0;i--){Adjust_Down(i);}}void push(const T& x){_con.push_back(x);Adjust_Up(_con.size() - 1);}void pop(){std::swap(_con[0], _con[_con.size() - 1]);_con.pop_back();Adjust_Down(0);}void Adjust_Down(int parent){Compare confunc;int child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && confunc(_con[child], _con[child + 1])){child++;}//默认建大堆if (confunc(_con[parent], _con[child])){std::swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else{break;}}}void Adjust_Up(int child){Compare confunc;int parent = (child - 1) / 2;while (child > 0){if (confunc(_con[parent], _con[child])){std::swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}size_t size(){return _con.size();}const T& top(){return _con.front();}bool empty(){return _con.empty();}private:Container _con;};
}

测试代码

void test()
{vector<int> v{ 1,2,3,4,5,6,7 };lyrics::priority_queue<int> pq(v.begin(), v.end());while (!pq.empty()){cout << pq.top() << ' ';pq.pop();}lyrics::priority_queue<int> pq1(v.begin(), v.end());pq1.push(8);cout << endl;cout << endl << pq1.size() << endl;while (!pq1.empty()){cout << pq1.top() << ' ';pq1.pop();}cout << endl << pq1.size() << endl;
}

在这里插入图片描述

总结

在本篇博客中,我们深入探讨了优先级队列(priority_queue)的实现及其在各种应用中的重要性。通过详细的代码示例,我们演示了如何利用堆数据结构高效地管理具有优先级的元素,展示了优先级队列在插入、查找和删除操作中的性能优势。无论是在调度算法、图算法还是操作系统任务管理中,优先级队列都展现出了不可或缺的作用。

此外,我们还介绍了仿函数(Functor)这一强大的编程概念。通过重载函数调用运算符,仿函数可以像普通函数一样使用,但同时具备存储状态、实现灵活逻辑和代码复用的优点。通过具体的C++和Python代码示例,我们展示了如何定义和使用仿函数,并讨论了其在标准模板库(STL)和实际编程中的应用场景。

总的来说,理解和掌握优先级队列和仿函数这两个概念,对于提升编程能力和编写高效、灵活的代码具有重要意义。希望通过本篇博客的讲解,读者能够更好地理解这两个重要的编程技术,并在实际项目中加以应用。如果你对优先级队列或仿函数有任何疑问或建议,欢迎在评论区留言,我们共同探讨、学习进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/23339.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

579页 | 工业数字孪生建模与应用(免费下载)

【1】关注本公众号&#xff0c;转发当前文章到微信朋友圈 【2】私信发送 工业数字孪生建模与应用 【3】获取本方案PDF下载链接&#xff0c;直接下载即可。 如需下载本方案PPT/WORD原格式&#xff0c;请加入微信扫描以下方案驿站知识星球&#xff0c;获取上万份PPT/WORD解决方…

节点间通路

题目链接 节点间通路 题目描述 注意点 图是有向图节点编号大于等于 0 小于 n图中可能存在自环和平行边 解答思路 初始想到的是使用广度优先遍历&#xff0c;从start开始&#xff0c;存储每个点所能到达的其他节点集合&#xff0c;直到到达target或者不能到达新的节点为止&…

“新高考”下分班怎么分?

来自安徽的张女士告诉我&#xff1a;上一年孩子升入了高中&#xff0c;但没想到才高一&#xff0c;孩子就面临了一个困难的挑选&#xff1a;312”分班&#xff01; 什么是312”分班呢&#xff1f;许多人或许不明白&#xff0c;便是要求学生在高一入学时&#xff0c;针对于3门必…

服务器数据恢复—raid5阵列磁盘坏道离线导致数据丢失的数据恢复案例

服务器数据恢复环境&#xff1a; 某品牌x3850 X5服务器&#xff0c;服务器上有一组由5块硬盘组建的raid5阵列&#xff08;包含一块热备盘&#xff09;&#xff0c;安装linux操作系统&#xff0c;运行oracle数据库。 服务器故障&#xff1a; 服务器上raid5阵列中两块硬盘由于未…

Vue进阶之Vue无代码可视化项目(四)

Vue无代码可视化项目 左侧栏第一步LeftPanel.vueLayoutView.vuebase.css第二步LayoutView.vueLeftPanel.vue编排引擎smooth-dnd安装创建文件SmoothDndContainer.tsutils.tsSmoothDndDraggable.tsLeftPanel.vue左侧栏 第一步 创建LeftPanel LeftPanel.vue <script setup…

空间数据采集与组织、转换与处理;统计数据、GPS数据、矢量数据、栅格数据、遥感云平台数据、点云数据、多维数据获取及处理

你还在为找不到合适的数据而苦恼吗&#xff1f;你还在面对大量数据束手无策&#xff0c;不知如何处理吗&#xff1f;对于从事生产和科研的人员来说&#xff0c;空间数据的采集与管理是地理信息系统&#xff08;GIS&#xff09;和空间分析领域的关键环节。通过准确高效地采集和管…

层出不穷的大模型产品如何选

目录 1.概述 2.使用体验分享 2.1.功能情况 2.2.内容生成质量 2.3.隐私安全性 2.4.小结 3.独特优势和倾向选择 4.未来发展方向 4.1.技术创新 4.2.可持续可扩展性 4.3.用户体验 4.4.应用场景 4.5.政府赋能 4.6.小结 1.概述 目前市面上的大模型AIGC产品有很多&#…

代码随想录——二叉搜索树中的插入操作(Leetcode701)

题目链接 递归 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {* …

如何理解与学习数学分析——第二部分——数学分析中的基本概念——第7章——连续性

第2 部分&#xff1a;数学分析中的基本概念 (Concepts in Analysis) 7. 连续性(Continuity) 本章首先讨论连续性的直观概念&#xff0c;并介绍与早期数学中常见的函数不同的函数。解释了连续性的定义&#xff0c;并演示了如何使用它来证明函数在一点上连续&#xff0c;以及证…

支付宝推出AI毛发自测工具,上传照片即可自测脱发等级

根据国家卫健委此前公布的数据&#xff0c;我国超过2.5亿人有脱发困扰&#xff0c;平均每6人中就有1人脱发&#xff0c;且近些年来&#xff0c;脱发群体呈年轻化趋势。为了帮助应对“秃”如其来的脱发问题&#xff0c;今日&#xff0c;支付宝发布“AI毛发自测”工具&#xff0c…

Mixly UDP局域网收发数据

一、开发环境 软件&#xff1a;Mixly 2.0在线版 硬件&#xff1a;ESP32-C3&#xff08;立创实战派&#xff09; 固件&#xff1a;ESP32C3 Generic(UART) 测试工具&#xff1a;NetAssist V5.0.1 二、实现功能 ESP32作为wifi sta连接到路由器&#xff0c;连接成功之后将路由器…

代码随想录 day 30

回溯总结&#xff1a; 相当于暴力for循环&#xff0c;其目的用递归控制for循环嵌套的数量。当剪枝时&#xff0c;就可以使得嵌套数量减少。把回溯问题抽象一颗树比较好懂。并且使得代码更简洁。 对于组合问题&#xff0c;什么时候需要startIndex呢&#xff1f; 在一个集合求组合…

计算机网络五层模型,看不懂请你去吃宵夜

大家好&#xff0c;我是徒手敲代码。 今天用最通俗易懂的话&#xff0c;来回答计算机网络五层模型&#xff0c;分别负责什么。 计算机网络的五层模型自底向上分别为物理层、数据链路层、网络层、传输层和应用层&#xff0c;每一层都承担着特定的职责&#xff0c;共同确保数据…

mysql8.0中的mysql.ibd

mysql8.0版本中多了一个mysql.ibd的文件。5.7版本则没有这个文件。 MySQL5.7: .frm文件 存放表结构信息 .opt文件&#xff0c;记录了每个库的一些基本 信息&#xff0c;包括库的字符集等信息 .TRN&#xff0c;.TRG文件用于存放触发器的信 息内容。 在MySQL 8.0之前&#xff0…

Qt for Android 申请摄像头权限

步骤 1. 添加用户权限 AndroidManifest.xml 中新增&#xff08;不添加后面申请选项时不弹窗&#xff09; 或者再Qt Creator中直接添加 2. Qt代码申请权限 Qt自己封装好了一些常用的权限申请&#xff0c; 详情Qt Assistant文档搜索 QPermission查看 #include <QPermi…

关于stm32的软件复位

使用软件复位的目的&#xff1a; 软件复位并不会擦除存储器中的数据&#xff0c;它只是将处理器恢复到复位状态&#xff0c;即中断使能位被清除&#xff0c;系统寄存器被重置&#xff0c;但RAM和Flash存储器中的数据保持不变。 STM32软件复位(基于库文件V3.5) &#xff0c;对…

终于搞懂了!原来vue3中template使用ref无需.value是因为这个

前言 众所周知&#xff0c;vue3的template中使用ref变量无需使用.value。还可以在事件处理器中进行赋值操作时&#xff0c;无需使用.value就可以直接修改ref变量的值&#xff0c;比如&#xff1a;<button click"msg Hello Vue3">change msg</button>。…

买视觉检测设备需要多少钱?

随着工业自动化的发展&#xff0c;其应用范围逐步提高&#xff0c;其中母子图像传感器、CMOS和CCD摄像机、DSP、ARM嵌入式技术、图像处理和模式识别技术的快速发展&#xff0c;有效地推动了视觉检测设备的发展。在机器视觉领域中&#xff0c;常见的就是视觉检测、视觉识别、视觉…

Django里choices字段使用中文使用

如果想要将下面的表格里的内容数字换成对应的内容&#xff1a; 需要更改成这样&#xff1a; 下面是步骤&#xff1a; 在 python 里的 models.py 文件里&#xff0c;创建数据表的时候&#xff0c;用到了 choices class Example(models.Model):name models.CharField(verbose…

领菲linfeeLNF96E多功能电力仪表智能数码液晶显示三相电压电流表

品牌 LINFEE 型号 LNF96E 货号 LNF96E 产地 中国大陆 省份 江苏省 地市 无锡市 装修及施工内容 安装工程 电源电路 交流电表 电表类型 多功能电度表 颜色分类 LNF96E-C,LNF96E-CM,LNF96E-CJ,LNF96E-CK,LNF96E-CJK,LNF96E-CMJK 多功能电力仪表,LNF96E三相多…