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

STL-priority_queue的使用及其模拟实现

      优先级队列(priority_queue)默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中的元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。

注意: 默认情况下priority_queue是大堆。

priority_queue的使用

priority_queue的构造函数

模板参数 Compare

在 std::priority_queue 类中,通过模板参数 Compare 来指定用于比较元素的函数对象,从而影响堆的排序方式。Compare 是一个仿函数,它定义了元素之间的比较方式。根据不同的 Compare,优先队列可以变成大堆(最大堆)或小堆(最小堆)。

默认的 std::less<T>(大堆):
std::less 是一个函数对象,它重载了 operator(),用于比较两个元素。它返回一个布尔值,表示是否第一个参数小于第二个参数。在默认情况下,如果不提供 Compare 参数,优先队列使用 std::less 作为比较函数对象,即大堆。这意味着在大堆中,父节点的值总是大于或等于子节点的值。

std::greater<T>(小堆):
std::greater<T> 是另一个函数对象,它重载了 operator(),用于比较两个元素。与 std::less<T> 不同,std::greater<T> 返回一个布尔值,表示第一个参数是否大于第二个参数。如果你将 std::greater<T> 传递给 priority_queue,它将会构造一个小堆。在小堆中,父节点的值总是小于或等于子节点的值。

仿函数

仿函数(Functor)是一种重载了函数调用操作符 operator() 的类对象,使得该对象可以像函数一样被调用。它实际上是一种函数对象,它可以具有自己的成员变量和操作,同时可以在使用上类似于普通函数。

使用仿函数的主要优点之一是可以将函数的行为和状态封装在对象中,从而使代码更具有可读性和可维护性。仿函数可以用于各种情况,包括标准算法、STL容器和其他需要函数式操作的地方。

例如:

// 仿函数/函数对象
template<class T>
class Less
{
public:
    bool operator()(const T& x, const T& y)
    {
        return x < y;
    }
};

empty():检查优先队列是否为空
size():用于获取优先队列中元素的数量
top():获取优先队列的顶部元素(最大或最小元素,取决于堆的类型),但不改变队列的内容
push():用于将新元素添加到优先队列中
emplace():在优先队列中插入一个新元素

pop():将优先队列的顶部元素移除,同时会重新调整堆以维持堆的性质

swap(): 用于交换调用对象和传递的参数 x 之间的内容,将两个优先队列的内容互换,但不会改变它们的比较函数或其他属性

模拟实现priority_queue

// Compare进行比较的仿函数 less->大堆
template<class T>
class Less
{
public:
    bool operator()(const T& x, const T& y)
    {
        return x < y;
    }
};


class Date
{
public:
    Date(int year = 1900, int month = 1, int day = 1)
        : _year(year)
        , _month(month)
        , _day(day)
    {}
    bool operator<(const Date& d)const
    {
        return (_year < d._year) ||
            (_year == d._year && _month < d._month) ||
            (_year == d._year && _month == d._month && _day < d._day);
    }
    bool operator>(const Date& d)const
    {
        return (_year > d._year) ||
            (_year == d._year && _month > d._month) ||
            (_year == d._year && _month == d._month && _day > d._day);
    }
    friend ostream& operator<<(ostream& _cout, const Date& d)
    {
        _cout << d._year << "-" << d._month << "-" << d._day;
        return _cout;
    }
private:
    int _year;
    int _month;
    int _day;
};

//类模板特化
template<>
struct Less<Date*>
{
    bool operator()(const Date* x, const Date* y)
    {
        return *x < *y;
    }
};

// Compare进行比较的仿函数 greater->小堆

template<class T>
class Greater
{
public:
    bool operator()(const T& x, const T& y)
    {
        return x > y;
    }
};
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 (com(_con[parent], _con[child]))
            //匿名对象
            //if (Compare()(_con[parent], _con[child]))
                //if (_con[parent] < _con[child])
            {
                swap(_con[child], _con[parent]);
                child = parent;
                parent = (child - 1) / 2;
            }
            else
            {
                break;
            }
        }
    }

    void adjust_down(int parent)
    {
        Compare com;
        size_t child = parent * 2 + 1;
        while (child < _con.size())
        {
            //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);
        adjust_up(_con.size() - 1);
    }

    void pop()
    {
        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;
};

class PDateLess {
public:
    bool operator()(const Date* p1, const Date* p2) {
        return *p1 < *p2;
    }
};
class PDateGreater{
public:
    bool operator()(const Date* p1, const Date* p2) {
        return *p1 > *p2;
    }
};
void test_priority_queue() {
    priority_queue<int> pq;
    pq.push(1);
    pq.push(2);
    pq.push(3);
    pq.push(4);
    pq.push(1);

    while (!pq.empty()) {
        cout << pq.top() << " ";
        pq.pop();
    }
    cout << endl;
}
void test_priority_queue2()
{
    // 大堆,需要用户在自定义类型中提供<的重载
    priority_queue<Date,vector<Date>,Less<Date>> q1;
    q1.push(Date(2018, 10, 29));
    q1.push(Date(2018, 10, 28));
    q1.push(Date(2018, 10, 30));
    cout << q1.top() << endl;
    priority_queue<Date*, vector<Date*>> q3;
    //priority_queue<Date*, vector<Date*>,PDateLess> q3;
    q3.push(new Date(2018, 10, 29));
    q3.push(new Date(2018, 10, 28));
    q3.push(new Date(2018, 10, 30));
    cout << *(q3.top()) << endl;
    // 如果要创建小堆,需要用户提供>的重载
    priority_queue<Date, vector<Date>, Greater<Date>> q2;
    q2.push(Date(2018, 10, 29));
    q2.push(Date(2018, 10, 28));
    q2.push(Date(2018, 10, 30));
    cout << q2.top() << endl;
}

成员函数的模拟实现

模板类 priority_queue:
这是一个模板类,它代表了一个优先队列的实现。它接受三个模板参数:T(元素类型),Container(底层容器类型,默认为 std::vector<T>),和 Compare(用于比较元素的仿函数,默认为 std::less<T>)

Compare 是一个模板参数,用于进行元素的比较。它是一个仿函数,可以是 std::less<T>(默认)或 std::greater<T>,具体取决于用户提供的优先队列类型。Compare 仿函数用于确定在堆中的元素排序方式,从而决定了是最大堆还是最小堆。在 priority_queue 类的各个成员函数中,通过调用 Compare 仿函数来进行元素的比较,从而实现了插入和调整堆的操作。

构造函数 priority_queue():
这是一个默认构造函数,不需要使用 Compare 仿函数进行比较。

构造函数模板 priority_queue(InputIterator first, InputIterator last):
在构造函数内部,使用 Compare 仿函数来执行比较操作,以确定元素的顺序。在添加元素后,通过调用 adjust_down 函数来构建堆。

成员函数 adjust_up(size_t child):
在上浮操作中,使用 Compare 仿函数执行比较,以确定是否需要交换父子节点的位置,从而保持堆的性质。

成员函数 push(const T& x):
在插入操作中,首先将新元素添加到底层容器 _con,然后通过调用 adjust_up 函数来执行上浮操作,保证新元素位于合适的位置。

成员函数 adjust_down(size_t parent):
在下沉操作中,使用 Compare 仿函数执行比较,以确定是否需要交换父子节点的位置,从而保持堆的性质。

成员函数 pop():
在删除操作中,首先将顶部元素与底层容器的最后一个元素交换,然后通过调用 adjust_down 函数来执行下沉操作,保证堆的性质。

成员函数 const T& top():
通过返回 _con[0],获取优先队列的顶部元素。

相关文章:

STL-priority_queue的使用及其模拟实现

优先级队列(priority_queue)默认使用vector作为其底层存储数据的容器&#xff0c;在vector上又使用了堆算法将vector中的元素构造成堆的结构&#xff0c;因此priority_queue就是堆&#xff0c;所有需要用到堆的位置&#xff0c;都可以考虑使用priority_queue。 注意&#xff1…...

pycharm连接阿里云服务器过程记录

因为不想用自己的电脑安装anaconda环境,所以去查了一下怎么用服务器跑代码,试着用pycharm连接阿里云服务器,参考了很多博客,自己简单配置了一下,记录一下目前完成的流程. 主要是:阿里云服务器的远程登录和安装anaconda,以及怎么用pycharm连接阿里云服务器上的解释器. 小白刚开始…...

移动硬盘未格式化数据恢复及预防策略

随着数字化时代的到来&#xff0c;移动硬盘作为数据存储的重要载体&#xff0c;被广泛应用于个人和企业中。然而&#xff0c;当移动硬盘遭遇“未格式化”的困境时&#xff0c;其中的数据便岌岌可危。本文将深入探讨移动硬盘未格式化的现象、原因、数据恢复方案以及预防措施&…...

MySQL数据库入门之视图、存储过程、触发器

一、视图&#xff1a; 1.1、视图是什么&#xff1f;怎么理解&#xff1f; 视图是从数据库的基本表&#xff08;或者视图&#xff09;导出的虚表&#xff08;数据库只放定义&#xff0c;它不实际存储数据&#xff0c;而是根据用户定义的SQL查询动态生成的结果集&#xff0c;具…...

Kafka原生API使用Java代码-生产者-分区策略-默认分区策略轮询分区策略

文章目录 1、代码演示1.1、pom.xml1.2、KafkaProducerPartitioningStrategy.java1.2.1、ProducerConfig.LINGER_MS_CONFIG取 0 值得情况&#xff0c;不轮询1.2.2、ProducerConfig.LINGER_MS_CONFIG取 0 值得情况&#xff0c;轮询1.2.3、ProducerConfig.LINGER_MS_CONFIG取 1000…...

网页中的音视频裁剪拼接合并

一、需求描述 项目中有一个配音需求&#xff1a; 1&#xff09;首先&#xff0c;前台会拿到一个英语视频&#xff0c;视频的内容是A和B用英语交流&#xff1b; 2&#xff09;然后&#xff0c;用户可以选择为某一个角色配音&#xff0c;假如选择为A配音&#xff0c;那么视频在播…...

【入门】使用sklearn实现的KNN算法:鸢尾花数据集分类预测

目录 前言 第一步&#xff1a;安装和导入sklean模块 第二步&#xff1a;获取数据 第二步&#xff1a;分割出训练集和测试集 第三步&#xff1a;训练模型 第四步&#xff1a;测试结果 总结 前言 本文将介绍如何利用K最近邻&#xff08;KNN&#xff09;算法对经典的鸢尾花数…...

nss做题

[NCTF 2018]签到题 1.f12在index.php中找到flag [NSSCTF 2022 Spring Recruit]ezgame 1.在js源码中就有flag [UUCTF 2022 新生赛]websign 1.打开环境后发现ctrlu和右键&#xff0c;f12都被禁用了。两种方法&#xff0c;第一种&#xff1a;禁用js&#xff1b;第二中提前打开…...

​第18章:JDK8-17新特性

1. 新特性概述 > 角度1&#xff1a;新的语法规则 &#xff08;多关注&#xff09;比如&#xff1a;lambda表达式、enum、annotation、自动拆箱装箱、接口中的默认方法和静态方法、switch表达式、record等> 角度2&#xff1a;增加、过时、删除API比如&#xff1a;新的日期…...

哈希表练习题(2024/5/29)

1有效的字母异位词 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每个字符出现的次数都相同&#xff0c;则称 s 和 t 互为字母异位词。 示例 1: 输入: s "anagram", t "nagaram" 输…...

java —— 连接 MySQL 操作

MySQL 是独立于 java 之外的数据库&#xff0c;二者之间建立连接需要提前引入 mysql-connector-java 的 jar 包。 一、引入方法&#xff1a; ① 在项目中新建一个 Folder&#xff08;即文件夹&#xff09;&#xff0c;该文件夹通常命名为 lib&#xff0c;意思是存放项目所依赖…...

从 0 开始实现一个博客系统 (SSM 项目)

相关技术 Spring Spring Boot Spring MVC MyBatis Html Css JS pom 文件我就不放出来了, 之前用的 jdk8 做的, MySQL 用的 5.7, 都有点老了, 你们自己看着配版本就好 实现功能 用户注册 - 密码加盐加密 (md5 加密)前后端用户信息存储 - 令牌技术用户登录 - (使用 拦截…...

C++标准模板(STL)- C 内存管理库 - 分配并清零内存 (std::calloc)

C 内存管理库 分配并清零内存 std::calloc void* calloc( std::size_t num, std::size_t size ); 分配 num 个大小为 size 的对象的数组&#xff0c;并初始化所有位为零。 若分配成功&#xff0c;则返回指向为任何对象类型适当对齐的&#xff0c;被分配内存块最低&#xf…...

嵌入式开发面试问题总结(持续更新)

面试问题总结 c/c 封装、继承和多态 封装&#xff1a;将属性和方法封装起来&#xff0c;并加以权限区分。继承&#xff1a;子类继承父类的特征和行为&#xff0c;复用了从基类复制而来的数据成员和成员函数&#xff08;基类私有成员无法被访问&#xff09;&#xff0c;其中构…...

意外发现openGauss兼容Oracle的几个条件表达式

意外发现openGauss兼容Oracle的几个条件表达式 最近工作中发现openGauss在兼容oracle模式下&#xff0c;可以兼容常用的两个表达式&#xff0c;因此就随手测试了一下。 查看数据库版本 [ommopenGauss ~]$ gsql -r gsql ((openGauss 6.0.0-RC1 build ed7f8e37) compiled at 2…...

使用Keepalived提高吞吐量和负载均衡ip_hash.

一 . Nginx使用Keepalived提高吞吐量案例 Keepalived[表示把连接保持一定长连接数来提高吞吐量] 1.1没有使用keepalived参数 upstream tomcats {server 192.168.28.102:8080; } server {listen 88;server_name www.tomcats.com;location / {proxy_pass http://to…...

网络故障与排除(一)

一、Router-ID冲突导致OSPF路由环路 路由器收到相同Router-ID的两台设备发送的LSA&#xff0c;所以查看路由表看到的OSPF缺省路由信息就会不断变动。而当C1的缺省路由从C2中学到&#xff0c;C2的缺省路由又从C1中学到时&#xff0c;就形成了路由环路&#xff0c;因此出现路由不…...

C++之运算符重载

1、运算符重载 //Complex.h #ifndef _COMPLEX_H_ #define _COMPLEX_H_class Complex { public:Complex(int real_, int imag_);Complex();~Complex();Complex& Add(const Complex& other); void Display() const;Complex operator(const Complex& other);privat…...

使用springdoc-openapi-starter-webmvc-ui后访问swagger-ui/index.html 报错404

按照官网说明&#xff0c;引入 springdoc-openapi-starter-webmvc-ui后应该就可以直接访问swagger-ui.html或者swagger-ui/index.html就可以出现swagger页面了&#xff0c;但是我引入后&#xff0c;访问提示报错404. 在我的项目中&#xff0c;有其他依赖间接引入了org.webjars…...

深入理解计算机系统 家庭作业4.52

练习题4.3 p.254 \sim\seq\seq-full.hcl文件内已经说的很清楚了哪些不能更改,哪些是题目要求更改的控制逻辑块. 依据家庭作业4.51的答案,在seq-full.hcl文件内更改对应的HCL描述即可 以下答案注释了#changed的就是更改部分 #/* $begin seq-all-hcl */ ######################…...

别再只用四线制SPI了!用菊花链连接多个传感器,Arduino引脚不够的救星

菊花链SPI&#xff1a;突破Arduino引脚限制的多传感器连接方案 当你在智能温室项目中需要同时监测温度、湿度和光照强度&#xff0c;却发现Arduino Uno的GPIO引脚已经捉襟见肘时&#xff0c;传统四线制SPI的局限性就暴露无遗。每个新增的传感器都意味着多占用一个宝贵的片选引…...

CosyVoice多语言语音合成体验:支持中英日韩粤,一键生成

CosyVoice多语言语音合成体验&#xff1a;支持中英日韩粤&#xff0c;一键生成 1. 开篇&#xff1a;语音合成新体验 想象一下&#xff0c;你正在制作一个面向全球市场的产品宣传视频&#xff0c;需要中文、英文、日语、韩语和粤语五种语言的配音。传统方式需要找五位不同语种…...

基于python框架的大学生创新创业项目管理系统vue

目录功能模块分析项目管理模块评审管理模块资源协同模块技术实现要点数据安全方案扩展性设计项目技术支持源码获取详细视频演示 &#xff1a;文章底部获取博主联系方式&#xff01;同行可合作功能模块分析 用户管理模块 角色划分&#xff1a;学生、导师、管理员&#xff08;支…...

手机续航的秘密武器:深入解读LPDDR5的Power Down与Deep Sleep省电机制

手机续航的秘密武器&#xff1a;深入解读LPDDR5的Power Down与Deep Sleep省电机制 当你的手机屏幕熄灭时&#xff0c;一场精密的节能芭蕾正在内存芯片内部上演。现代智能手机中&#xff0c;LPDDR5内存的功耗可能占到整机待机功耗的30%以上&#xff0c;而Power Down与Deep Sleep…...

conda安装cudnn避坑指南:为什么你的CUDA环境总是报错?

Conda环境下的CUDA与cuDNN版本管理实战指南 每次在终端看到CUDA相关的报错信息时&#xff0c;那种感觉就像是在解一道没有标准答案的数学题。特别是当深度学习框架因为CUDA版本不兼容而拒绝运行时&#xff0c;连最简单的import tensorflow都能变成一场噩梦。本文将带你深入理解…...

5个步骤用开源工具实现低延迟实时字幕:从配置到优化的完整指南

5个步骤用开源工具实现低延迟实时字幕&#xff1a;从配置到优化的完整指南 【免费下载链接】VideoCaptioner &#x1f3ac; 卡卡字幕助手 | VideoCaptioner - 基于 LLM 的智能字幕助手&#xff0c;无需GPU一键高质量字幕视频合成&#xff01;视频字幕生成、断句、校正、字幕翻译…...

别再傻傻用远程桌面了!手把手教你用华为服务器自带的KVM工具(附初始IP和密码)

华为服务器KVM工具实战指南&#xff1a;解锁高效运维新姿势 第一次接触华为服务器时&#xff0c;我和大多数运维新手一样&#xff0c;本能地打开远程桌面连接工具&#xff0c;输入IP地址准备登录。直到某次机房网络故障&#xff0c;我才发现华为早已在服务器中内置了一把"…...

macOS Monterey安装OpenClaw:对接Qwen3-32B镜像全记录

macOS Monterey安装OpenClaw&#xff1a;对接Qwen3-32B镜像全记录 1. 为什么选择OpenClaw与Qwen3-32B组合 去年冬天第一次接触OpenClaw时&#xff0c;我正被重复性的文件整理工作折磨得焦头烂额。当时试过几个自动化工具&#xff0c;要么功能太局限&#xff0c;要么需要把数据…...

WarcraftHelper:开源工具赋能魔兽争霸3现代硬件适配与性能优化全指南

WarcraftHelper&#xff1a;开源工具赋能魔兽争霸3现代硬件适配与性能优化全指南 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper WarcraftHelper是一款…...

数字电路设计小技巧:从HDLBits例题看SOP与POS的Verilog实现

数字电路设计实战&#xff1a;从真值表到Verilog的SOP与POS高效实现 在数字电路设计中&#xff0c;掌握逻辑表达式的最简化方法是一项基础但至关重要的技能。今天我们就以HDLBits平台上的经典例题ECE241 2013 Q2为例&#xff0c;手把手教你如何从真值表出发&#xff0c;通过卡…...