【C++优先队列使用】问题总结

news2024/9/9 0:35:21

说明

  1. 文章内容为关于priority_queue的使用总结,在C++中要包含头文件<queue>
  2. 文章内容为个人的学习整理,如有错误,欢迎指正。

文章目录

  • 1. 优先队列默认是大根堆
  • 2. 关于优先队列和sort的比较逻辑
    • 2.1 sort的比较逻辑
    • 2.2 优先队列的比较逻辑
      • 2.2.1 优先队列的验证
      • 2.2.2 sort的验证
    • 2.3 优先队列和sort比较逻辑的区别简记
  • 3. 自定义比较逻辑

1. 优先队列默认是大根堆

优先队列默认使用大根堆结构,例如:

int main()
{
    vector<int> v = {0,1,2,3,4,5,6,7,8,9};
    priority_queue<int> pq;
    for(int i=0; i<v.size(); i++)
        pq.push(v[i]);  
    while(!pq.empty())
    {
        cout<<pq.top()<<" ";
        pq.pop();
    }
    return 0;
}

输出结果为:

9 8 7 6 5 4 3 2 1 0

默认的输出序列是一个降序序列。

2. 关于优先队列和sort的比较逻辑

2.1 sort的比较逻辑

而sort的默认输出结果是升序的。sort的默认比较逻辑是less<>,因此对于vector<int> v = {0,1,2,3,4,5,6,7,8,9};有以下结果:

sort(v.begin(), v.end()); //输出为0 1 2 3 4 5 6 7 8 9 
sort(v.begin(), v.end(),less<>()); //0 1 2 3 4 5 6 7 8 9 
sort(v.begin(), v.end(),greater<>());//9 8 7 6 5 4 3 2 1 0

2.2 优先队列的比较逻辑

优先队列和sort比较逻辑的区别(这也是我之前理解的一个误区),还是对上面的数组,由优先队列输出的结果为:

priority_queue<int, vector<int>> pq;//9 8 7 6 5 4 3 2 1 0 
priority_queue<int, vector<int>, less<int>> pq;//9 8 7 6 5 4 3 2 1 0 
priority_queue<int, vector<int>, greater<int>> pq;//0 1 2 3 4 5 6 7 8 9 

优先队列默认输出是大根堆的输出,即结果是升序的,但它的默认比较逻辑是less<>。
这里我一直想不明白为什么相同的比较逻辑却得到不同的输出结果,多方查阅资料后,有解释说是因为传参的顺序不同。例如cmp<int a, int b>,a,b作为比较逻辑中的两个参数,新参与比较的元素是作为第一个参数还是第二个元素,这个差异导致了sort和priority_queue输出了不同的结果。下面来简单验证一下:

2.2.1 优先队列的验证

结论:优先队列将未进入队列的元素作为cmp的第二个参数传入。
验证如下:

  1. 定义比较逻辑
//priority_queue比较逻辑
struct cmp_2
{
	bool operator() (int a, int b)
	{        	
        cout<<"priority_q cmp: "<<a<<" "<<b<<endl;    
        return a < b;
	}
};
  1. 定义优先队列并输入数据,观察元素在入队过程中的比较过程
	priority_queue<int, vector<int>, cmp_2> pq;	
	pq.push(1); 
	pq.push(2); 
	pq.push(3); 
	pq.push(4); 
	pq.push(5);

将1~5依次入队,这个过程中的输出为:

priority_q cmp: 1 2
priority_q cmp: 2 3
priority_q cmp: 1 4
priority_q cmp: 3 4
priority_q cmp: 3 5
priority_q cmp: 4 5

比较过程的简图如下:
在这里插入图片描述
可见每次新入队的元素都作为cmp的第二个参数参与比较。优先队列是用大根堆实现的,因此图中的cmp过程也就是大根堆的调整过程。
之后依次弹出堆顶也就是出队的过程,就得到了一个降序序列(大根堆,堆顶元素最大)

2.2.2 sort的验证

结论:sort将未排好的元素作为cmp的第一个参数传入。
验证如下:

  1. 定义比较逻辑
bool cmp_1 (int a, int b)
{   
    cout<<"sort cmp: "<<a<<" "<<b<<endl;
    return a < b;
}
  1. 创建数组输入元素,执行sort函数,观察元素在排序过程中的比较情况
 	vector<int> nums;
    nums.push_back(5);
    nums.push_back(4);
    nums.push_back(3);
    nums.push_back(2);
    nums.push_back(1); 
    sort(nums.begin(), nums.end(), cmp_1);  

将5~1一次存入数组,之后执行sort函数,这个过程的输出为:

sort cmp: 4 5
sort cmp: 3 4
sort cmp: 2 3
sort cmp: 1 2

比较过程的简图如下:(说明:sort的底层是内省式排序和插入排序,所以下图中的比较过程并不完整,仅仅是为了显示参与比较的元素是作为第几个参数传入的
在这里插入图片描述可见每次未排好的元素作为cmp的第一个参数传入,

2.3 优先队列和sort比较逻辑的区别简记

说明:下面的方法是我个人为了方便理解而整理的方法,可能有不严谨的地方,各位酌情观看。

输出序列的优先级:高--->低
sortless : 1,2,3,4,5值越小,优先级越高
greater:5,4,3,2,1值越大,优先级越高
priority_queueless:5,4,3,2,1值越大,优先级越高
greater:1,2,3,4,5值越小,优先级越高

记忆的话,sort就正着记:

  • less就是升序,排在前面的比后面小,前less后
  • greater就是降序,排在前面的比后面的大,前greater后

优先队列就反着记:(其实和优先队列是大根堆有关)

  • less就是降序,排在前面的比后面大,后less前
  • greater就是升序,排在前面的比后面小,后greater前

3. 自定义比较逻辑

最后做个小实验,自定义比较逻辑,验证结果的正确性。

#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;

struct node
{
	int x,y;
}A;

//定义sort的比较逻辑
bool cmp_1 (node a, node b)
{
    if(a.x != b.x) return a.x < b.x;
    else return a.y > b.y;
}
//定义priority_queue的比较逻辑
struct cmp_2
{
    bool operator() (node a, node b)
    {
        if(a.x != b.x) return a.x < b.x;
        else return a.y > b.y;
    }
};

int main()
{
    priority_queue<node, vector<node>, cmp_2> pq;
    vector<node> v;
    A.x = 1, A.y = 9, pq.push(A), v.push_back(A);
    A.x = 1, A.y = 8, pq.push(A), v.push_back(A);
    A.x = 2, A.y = 9, pq.push(A), v.push_back(A);
    A.x = 3, A.y = 9, pq.push(A), v.push_back(A);
    A.x = 4, A.y = 6, pq.push(A), v.push_back(A);

    sort(v.begin(), v.end(), cmp_1);
    cout<<"sort cmp result"<<endl;
    for(int i=0; i<v.size(); i++) 
        cout<<v[i].x<<" "<<v[i].y<<endl;
    
    cout<<"priority_queue cmp result"<<endl;
    while(!pq.empty())
    {
        cout<<pq.top().x<<" "<<pq.top().y<<endl;
        pq.pop();
    }
    return 0;
}

输出结果为:

sort cmp result
1 9
1 8
2 9
3 9
4 6
priority_queue cmp result
4 6
3 9
2 9
1 8
1 9

其实关于sort和优先队列的自定义比较逻辑都是

	if(a.x != b.x) return a.x < b.x;
    else return a.y > b.y;

可以看到输出结果恰好相反,就对应了sort的less和greater逻辑和优先队列的less和greater逻辑是相反的。

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

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

相关文章

【学术综述】-如何写出一篇好综述-写好综述要注意的问题

文章目录 1.前置1.1 SSD 的结构1.2 FTL的架构和作用 2 动机-why&#xff1f;3 做了什么【做了哪些方面的survey】&#xff1f;4 背景知识【上下文】5 研究的问题6 每个问题对应的解决方案 从昨天晚上【2023.11.09 22:00】到今天22:29的&#xff0c;花了一天的时间在读这篇surve…

gcc [linux]

目录 背景知识 gcc如何完成 格式 预处理&#xff08;进行宏替换&#xff09; 编译&#xff08;生成汇编&#xff09; 汇编&#xff08;生成机器可执行码&#xff09; 连接&#xff08;生成可执行文件或库文件&#xff09; 函数库 静态库 静态链接优势 动态库 动态链…

Ubuntu配置Yolov8环境并训练自己的数据集

文章目录 一、环境配置与功能测试1.1 安装1.2 目标检测1.3 实例分割1.4 分类1.5 姿态检测 二、训练数据标注三、数据集训练方法3.1 命令训练3.2 代码训练 前言&#xff1a;需要先安装CUDA和Anaconda&#xff0c;它们的安装参考我这篇文章&#xff1a;Ubuntu配置深度学习环境&am…

局域网下搭建SVN服务器

文章目录 1. 下载SVN服务器(VisualSVN Server)2. 安装SVN服务器(VisualSVN Server)3. 下载并安装TortoiseSVN4. 搭建SVN服务器 1. 下载SVN服务器(VisualSVN Server) 下载地址 2. 安装SVN服务器(VisualSVN Server) 默认安装即可 Location&#xff1a;VisualSVN Server的安装…

SpringBoot前后端分离整合cas(客户端)

SpringBoot前后端分离整合cas&#xff08;客户端&#xff09; cas认证详细流程&#xff1a; 前后端分离&#xff1a;项目前端使用nginx启动&#xff0c;后端是springBoot服务&#xff1b; nginx可以统一管理Cookie&#xff0c;避免出现跨域问题。 添加依赖 <dependency&g…

探索未来,开启无限可能:打造智慧应用,亚马逊云科技大语言模型助您一臂之力

文章目录 什么是大模型&#xff1f;大模型训练方法亚马逊云科技推出生成式AI新工具 —— aws toolkit使用教程 总结 什么是大模型&#xff1f; 近期&#xff0c;生成式大模型是人工智能领域的研究热点。这些生成式大模型&#xff0c;诸如文心一言、文心一格、ChatGPT、Stable …

strcat()用法

描述 头文件&#xff1a;<string.h>char *strcat&#xff08;char *dest&#xff0c; const char *src&#xff09;功能&#xff1a;将src字符串加到dest上&#xff0c;并返回指向dest字符串的指针。 举例 #include<stdio.h> #include<string.h> int mai…

使用非递归的方式实现归并排序

使用非递归的方式实现归并排序 话不多说&#xff0c;直接上代码&#xff1a; public class MergySort {public static void main(String[] args) {int[] nums {38, 27, 43, 3, 9, 82, 10};int[] sortedArray MergySort.mergySort(nums);// 输出排序后的数组for (int num : …

神仙打架!腾讯云阿里云谁更棋高一着?

现在&#xff0c;腾讯云和阿里云都在打价格战&#xff0c;推出了一系列的优惠政策。其中&#xff0c;腾讯云服务器只需要88元&#xff0c;而阿里云服务器也只需要99元。这么便宜的价格&#xff0c;是不是让你心动不已呢&#xff1f; 腾讯云的88元服务器&#xff1a;https://te…

CG Magic分享如何解决Vray渲染器使用不了的问题?

大家在使用Vray渲染器时&#xff0c;经常会有网友反馈说&#xff0c;为什么Vray渲染器使用不了的情况&#xff1f; vray渲染器是安装中出了问题嘛&#xff0c;还是什么原因呢&#xff1f;导致vray渲染器渲染不了。 那么&#xff0c;vray渲染器怎么安装才能正常使用呢&#xff…

java try catch 异常后还会继续执行吗

1、有 try-catch 语句块&#xff0c;并且 throw 在 catch 语句块里&#xff0c;那么 try 语句块中引发异常&#xff08;报错&#xff09;的那一行代码的后续代码都不执行并且 catch 语句块后的代码也都不执行&#xff08;遇到 finally 除外&#xff09;。&#xff08;见情形一和…

已解决:Rust Error: the trait bound is not satisfied 问题

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…

C# 同步异步大白话

同步异步大白话 背景 任务异步编程模型&#xff08;TAP&#xff09;提供了对异步代码的抽象。您可以像往常一样&#xff0c;将代码编写为一系列语句。您可以阅读该代码&#xff0c;就好像每条语句都在下一条语句开始之前完成一样。编译器执行许多转换&#xff0c;因为其中一些…

最详细的LightGBM参数介绍与深入分析

前言 我使用LightGBM有一段时间了&#xff0c;它一直是我处理大多数表格数据问题的首选算法。它有很多强大的功能&#xff0c;如果你还没有看过的话&#xff0c;我建议你去了解一下。 但我一直对了解哪些参数对性能影响最大&#xff0c;以及如何调整LightGBM参数以发挥最大作用…

使用WinDbg分析CPU100%的问题

在我们软件运行的时候&#xff0c;偶尔会出现CPU占比100%的问题&#xff0c;而且极其不容易排查&#xff0c;概率极低&#xff0c;我硬是操作了一个下午&#xff0c;出现了一次&#xff0c;然后找到了dmp文件&#xff0c;也没有任何的规律&#xff0c;那么就可以借助windbg进行…

二维码解码器怎么用?快速分解二维码图片的方法

现在很多人会将链接网址生成二维码之后来使用&#xff0c;这种方式能够让别人更快的获取链接的内容&#xff0c;而且扫码访问内容的方式也更适合大家的使用习惯。那么如果想要获取二维码中的链接时&#xff0c;一般会使用二维码解码器来处理&#xff0c;那么具体该怎么使用呢&a…

nodejs express multer 保存文件名为中文时乱码,问题解决 originalname

nodejs express multer 保存文件名为中文时乱码&#xff0c;问题解决 originalname 一、问题描述 用 express 写了个后台&#xff0c;在接收文件并保存的时候 multer 接收到的文件名为乱码。 二、解决 找了下解决方法&#xff0c;在 github 的 multer issue 中找到了答案 参…

Ubuntu 22.04 安装水星无线 USB 网卡

我的 USB 网卡是水星 Mercury 的&#xff0c; 在 Ubuntu 22.04 下面没有自动识别。 没有无线网卡的时候只能用有线接到路由器上&#xff0c;非常不方便。 寻思着把无线网卡驱动装好。折腾了几个小时装好了驱动。 1.检查网卡类型 & 安装驱动 使用 lsusb 看到的不一定是准确…

归并排序之确定递归层数

题目 给定一维int型数组a[0,1,…,n-1], 使用归并排序方法, 对其进行从小到大排序, 请输出递归过程中自顶自下第三层的排序结果, 其中最顶层为第一层, 即最终的排序结果层. 归并排序划分请按a[0,mid(0n-1)/2], a[(0n-1)/21, n-1]进行划分子问题. Input 输入第1行有一个int型正…

AI由许多不同的技术组成,其中一些最核心的技术如下

AI由许多不同的技术组成&#xff0c;其中一些最核心的技术包括&#xff1a; 机器学习&#xff1a;这是一种让计算机从数据中学习的技术&#xff0c;它可以根据已有的数据预测未来的趋势和行为。机器学习包括监督学习、无监督学习和强化学习等多种类型。深度学习&#xff1a;这…