【C++】优先级队列(priority_queue)的用法与实现

news/2024/11/17 1:28:18/

目录

一、概念:

二、仿函数(Functor):

概念:

应用:

三、底层实现:

基本操作:

完整代码:

测试示例:


一、概念:

        优先级队列(priority_queue)在功能上类似于堆(heap)这个数据结构,在优先级队列中,元素的出队顺序(或检索顺序)基于它们的优先级,而不是它们进入队列的顺序。具有最高优先级的元素将最先出队,而具有最低优先级的元素将最后出队(或反之,取决于具体实现),就像是在大堆中堆顶元素是堆中最大的值,在删除堆顶元素时总是删除的最大值,而不是取决于它们入堆的顺序。

定义:

#include <queue> // 引头文件// 类似于大堆; less表示按照递减(从大到小)的顺序插入元素
priority_queue<int, vector<int>, less<int>> s; // 类似于小堆; greater表示按照递增(从小到大)的顺序插入元素
priority_queue<int, vector<int>, greater<int>> s; 

二、仿函数(Functor)

概念:

        仿函数(Functor)也称为函数对象,是一种可调用的对象,一般通过重载函数调用操作符(operator())来实现。这使得仿函数类具有像函数一样的特性:可以接受参数并返回值。

        仿函数的目的为:使一个类的使用看上去像一个函数,从而方便地应用于算法、STL容器以及其他需要函数对象的场合。

仿函数的优点:

        1、可以拥有状态,这意味着仿函数可以在运行时动态地改变其行为。

        2、与纯函数相比,仿函数在某些情况下可能具有更快的执行速度。

注意:

        仿函数并不是真正的函数,而是具有函数行为的类对象。因此,它们可以像类一样存储和访问数据,同时又具有函数的调用特性。

应用:

例如在C++ algorithm 库 中的 sort 函数 的第三个参数:

template<class RandomIt, class Compare>  
void sort(RandomIt first, RandomIt last, Compare comp);

comp:(可选):一个接受两个参数并返回一个布尔值的函数或函数对象

默认的排序是升序,此时我们不用库中提供的降序仿函数,自己实现一个简单的降序仿函数:

template<class T>
struct Greater // 函数对象(仿函数)功能实现
{bool operator()(const T& x, const T& y){return x > y;}
};void Test()
{vector<int> v = { 5,3,7,8,3,0,6,3,1,2,9 };sort(v.begin(), v.end(), Greater<int>()); // 匿名调用// Greater<int> s1;// sort(v.begin(), v.end(), s1); // 显式调用for (auto e : v){cout << e << " ";}
}

三、底层实现:

基本操作:

1、push():将元素入队列。操作与堆类似,向尾部插入并不断向上调整至合适位置】 

2、pop():删除队列中优先级最高的元素。【操作与堆类似,首尾交换后删除尾部,队头元素不断向下调整至合适位置】

3、top():获取并返回队列中优先级最高的元素。

4、size():获取并返回队列大小。【返回值为 unsigned int(size_t)类型】

5、empty():判断队列是否为空。【返回值为bool类型。队列为空返回true,不空返回false】

完整代码:

template<class T>
struct Less
{bool operator()(const T& x, const T& y){return x < y;}
};template<class T>
struct Greater
{bool operator()(const T& x, const T& y){return x > y;}
};template<class T, class Con = vector<T>, class Com = Less<T>>
class priority_queue
{
public:// 向上调整void adjust_up(int child){Com com; // 模板实例化一个函数对象,默认Less,取小int parent = (child - 1) / 2;while (child > 0){//if (_con[child] > _con[parent])// if(_con[parent] < _con[child])if (com(_con[parent], _con[child])) // 为真执行,为假跳出{swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else{break;}}}// 向下调整void adjust_down(size_t parent){Com com;size_t child = parent * 2 + 1;while (child < _con.size()){// 找左右孩子中大的那个与父节点交换,换算关系如下//if (child + 1 < _con.size() && _con[child + 1] > _con[child])//if (child + 1 < _con.size() && _con[child] < _con[child + 1])if (child + 1 < _con.size() && com(_con[child], _con[child + 1])){++child;}//if (_con[child] > _con[parent])//if (_con[parent] < _con[child])if (com(_con[parent], _con[child])){swap(_con[parent], _con[child]);parent = child;child = parent * 2 + 1;}else{break;}}}void push(const T& val){_con.push_back(val);adjust_up(_con.size() - 1); // 传入刚插入的子节点下标}void pop(){swap(_con[0], _con[_con.size() - 1]);_con.pop_back();adjust_down(0);}const T& top() const{return _con[0];}size_t size(){return _con.size();}bool empty(){return _con.empty();}
private:Con _con;
};

测试示例:

给一个数组(升序)以此按序进入队列,此时优先级队列的功能类似大堆,应该按照降序返回:

int main()
{vector<int> v = { 1,2,3,4,5,6,7,8,9,10 };priority_queue<int> q1; // 默认大堆 Lessfor (auto i : v){q1.push(i);}while (!q1.empty()){cout << q1.top() << " ";q1.pop();}return 0;
}

测试结果:


http://www.ppmy.cn/news/1412383.html

相关文章

vue2 el-checkbox-group 复选框无法选中

vue2 el-checkbox-group 复选框无法选中 原代码&#xff1a; <template slot-scope"scope"><el-checkbox v-model"scope.row.bitian">必填</el-checkbox> </template>if (this.allTemplateList && this.allTemplateList…

OpenHarmony开发-连接开发板调试应用

在 OpenHarmony 开发过程中&#xff0c;连接开发板进行应用调试是一个关键步骤&#xff0c;只有在真实的硬件环境下&#xff0c;我们才能测试出应用更多的潜在问题&#xff0c;以便后续我们进行优化。本文详细介绍了连接开发板调试 OpenHarmony 应用的操作步骤。 首先&#xf…

lora微调过程

import os import pickle from transformers import AutoModelForCausalLM from peft import get_peft_config, get_peft_model, get_peft_model_state_dict, LoraConfig, TaskTypedevice "cuda:0"#1.创建lora微调基本的配置 peft_config LoraConfig(task_typeTask…

python 会员管理系统

问题介绍 综合案例&#xff1a;会员管理系统实现-V2版&#xff08;不可超前使用面向对象&#xff09; 利用函数&#xff0c;编写会员管理系统&#xff0c;实现进入系统显示系统功能界面&#xff0c;选择添加、删除、修改&#xff0c;查询、显示所有会员信息以及退出系统等响应…

【13137】第一章 质量与质量管理导论

目录 1.单选题 2.多选题 3.简答题 【13137】质量管理-考试分析: 1.单选题

基于SpringBoot注入Bean形式的监听(端口)

起一个线程、监听对应的端口,注入到容器 package com.port.component;import com.port.service.PortListenerService; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.stereoty…

线性变换在人工智能领域的深度实践与应用探索

线性变换&#xff0c;作为数学中的一种基本工具&#xff0c;在人工智能领域中发挥着举足轻重的作用。其强大的表示能力和灵活的运算特性使得线性变换成为机器学习、深度学习等多个子领域的核心组成部分。本文将详细探讨线性变换在人工智能领域中的实践应用&#xff0c;旨在揭示…

【攻防世界】web2(逆向解密)

进入题目环境&#xff0c;查看页面信息&#xff1a; <?php $miwen"a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws";function encode($str){$_ostrrev($str);// echo $_o;for($_00;$_0<strlen($_o);$_0){$_csubstr($_o,$_0,1);$__ord($_c)1;…