C++修炼之路之STL_priority_queue优先级队列和仿函数

ops/2024/10/21 7:49:44/

目录

引言: 

一:priority_queue的介绍 

二:了解堆结构及对应的各种对应操作

三:priority_queue的接口函数及使用 

1.接口函数

2.使用 

四:仿函数operator()

 五:用仿函数加容器适配器模拟实现priority_queue

 六:本文相关代码连接

接下来的日子会顺顺利利,万事胜意,生活明朗-----------林辞忧

引言: 

在上篇STL中的queue中还有一个叫做优先级队列的知识点

它的结构类似于堆,默认它是大堆,即第一个元素总是他的数据中最大的一个,要想修改为小堆,就要使用仿函数的知识,接下来我们就介绍它

一:priority_queue的介绍 

1.优先级队列是一种容器适配器,根据严格的标准,它的第一个元素总是他包含元素中最大的,默认为大堆结构

2.结构类似于堆,在堆中可以随时插入数据,只能检索到最大堆元素(位于顶部的元素)

3.优先级队列被实现为容器适配器,可以封装其他容器来实现自身结构和功能 

4.容器deque和vector都满足优先级队列的结构,默认为vector

5.支持随机访问迭代器,始终能保持内部堆结构,容器可以调用算法库中 的make_heap,push_heap和pop_heap来完成对应的操作

二:了解堆结构及对应的各种对应操作

https://blog.csdn.net/Miwll/article/details/136636869?spm=1001.2014.3001.5501

三:priority_queue的接口函数及使用 

1.接口函数

2.使用 

#include <iostream>
#include <queue>
using namespace std;
int main()
{//priority_queue<int> p1;//priority_queue<int, vector<int>, less<int>> p1;//大堆priority_queue<int, vector<int>, greater<int>> p1;//小堆p1.push(1);p1.push(4);p1.push(2);p1.push(10);p1.push(7);p1.push(13);while (!p1.empty()){cout << p1.top() << " ";p1.pop();}return 0;
}

对于优先级队列他的插入删除数据的效率就是堆插入删除数据的效率,即log(N),效率很高 

对于后面的less和greater就是仿函数,接下来就将介绍它

四:仿函数operator()

仿函数就是重载了(),使用的时候像一个函数调用,使用它来替换函数指针

在标准库中常用的仿函数有less和greater来充当比较模板

也可以由我们自己编写自己需要的数据比较形式

常见的greater和less的实现

//仿函数
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;}
};
void testqueue2()
{Less<int> less1;//函数对象cout << less1(1, 4) << endl;Greater<double> g1;cout << g1(2.2, 4.4) << endl;priority_queue<int, vector<int>, Greater<int>> p1;//小堆p1.push(1);p1.push(4);p1.push(2);p1.push(10);p1.push(7);p1.push(13);while (!p1.empty()){cout << p1.top() << " ";p1.pop();}
}

对于less和greater不能比较完成的,比如 对于new出来的日期对象,使用less和greater来比较的话,比较的是他们的指针,这就会使结果随机,随意此时我们可以自己定比较规则来比较

struct PDateCompare
{bool operator()(Date* p1, Date* p2){return *p1 > *p2;}
};priority_queue<Date*, vector<Date*>, PDateCompare> q2;
q2.push(new Date(2018, 10, 29));
q2.push(new Date(2018, 10, 28));
q2.push(new Date(2018, 10, 30));
cout << *(q2.top()) << endl;

这里还有特殊的一点是对于库中sort算法和priority_queue中在传参的时候不同

 

 五:用仿函数加容器适配器模拟实现priority_queue

#pragma once
namespace mjw
{template <class T,class Container=vector<T>,class Compare=Less<T>>class priority_queue{public:priority_queue()//默认构造{}//迭代器区间构造template<class Inputiterator>priority_queue(Inputiterator first, Inputiterator last):_con(first,last){for (int i = (_con.size() - 2) / 2; i >= 0; --i)//建堆{adjust_down(i);}}void adjust_up(int child){Compare com;int parent = (child - 1) / 2;while (child > 0){//if(_con[parent]<_con[child])if (com(_con[parent], _con[child])){std::swap(_con[parent], _con[child]);child = parent;parent= (child - 1) / 2;}else{break;}}}void adjust_down(int parent){Compare com;int child = parent * 2 + 1;while (child < _con.size()){if (child + 1 < _con.size() && com( _con[child] , _con[child + 1])){++child;}if (com(_con[parent], _con[child])){std::swap(_con[parent], _con[child]);parent = child;child = parent * 2 + 1;}else{break;}}}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);}const T& top(){return _con[0];}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}

 

对于优先级队列的知识就是这了,但在OJ题中很常见题型,需要多加练习掌握 

 六:本文相关代码连接

https://gitee.com/lin-ciyu/cplusplus/tree/master/%E4%BC%98%E5%85%88%E7%BA%A7%E9%98%9F%E5%88%97%E4%BD%BF%E7%94%A8%E5%8F%8A%E6%A8%A1%E6%8B%9F%E5%AE%9E%E7%8E%B0/priority_queue


http://www.ppmy.cn/ops/15519.html

相关文章

基础算法前缀和与差分

前言 本次博客会介绍一维和二维的前缀和&#xff0c;以及一维二维差分的基本使用&#xff0c;尽量画图&#xff0c;多使用配合文字 使大家理解&#xff0c;希望有所帮助吧 一维前缀和 问题描述 这里有一个长度为n的数组&#xff0c;我们要算出【2,5】区间的元素和 暴力思…

GO 的 Web 开发系列(八)—— Gin 自定义 Html 渲染实现多租户的模板设计

本文主要解决在多租户场景下的模板渲染问题。 正常情况下 Gin 配置的所有模板都属于同一个模板组合,相同名称的模板将相互覆盖。在未通过 define 指定模板名称时,同名模板文件也将相互覆盖。自定义函数中也无法区分租户,这将非常不方便我们进行多租户的模板渲染处理。通过自…

ProtoBuf、Grpc、GORM、Go-redis 入门基础

一、ProtoBuf、Grpc ProtoBuf定义&#xff1a;protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法&#xff0c;它可用于&#xff08;数据&#xff09;通信协议、数据存储等。 说白了&#xff0c;可以将ProtoBuf文件 当作支持语言的代码交换工具 Grpc…

【前端】vue数组去重的3种方法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、数组去重说明二、Vue数组去重的3种方法 前言 随着开发语言及人工智能工具的普及&#xff0c;使得越来越多的人会主动学习使用一些开发工具&#xff0c;本文…

对观察者模式的理解

目录 一、场景1、题目描述 【[案例来源](https://kamacoder.com/problempage.php?pid1075)】2、输入描述3、输出描述4、输入示例5、输出示例 二、实现三、更复杂的场景 【[案例来源](https://refactoringguru.cn/design-patterns/observer/java/example#example-0--listeners-…

时间默认显示当前日期及系统时间

要将 xtdsSj 绑定到当前日期和系统时间&#xff0c;你可以在组件的 data 中初始化 xtdsSj 属性为当前日期及系统时间的字符串。然后&#xff0c;在组件创建时更新 xtdsSj&#xff0c;确保它始终显示当前日期和系统时间。 1.系统读数时间默认显示当前日期及系统时间 <templa…

自然语言生成软件!用码上飞CodeFlying来开发一个ChatBot

前言&#xff1a; 众所周知&#xff0c;2023年被称之为大模型的元年&#xff0c;随着ChatGPT的爆火&#xff0c;国内也涌现了诸多大模型的产品&#xff0c;从文生文、文生图片再到文生视频等多模态的应用成为了各家的主战场。但是在软件开发的领域&#xff0c;当前大部分的产品…

Flink Graph演变

1.概述 Flink 集群中运行的 Job&#xff0c;最终归根到底&#xff1a;还是构建一个高效能分布式并行执行的DAG执行图。一个 Flink 流式作业从 Client 提交到 Flink 集群到最后执行&#xff0c;总共经历 4 种状态&#xff0c;总体来说&#xff1a;Flink中的执行图可分成四层&…