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

说明

  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逻辑是相反的。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python操作链接数据库和Mysql中的事务在python的处理

python操作数据库 pymysql模块: pip install pymysql作用:可以实现使用python程序链接mysql数据库&#xff0c;且可以直接在python中执行sql语句 添加操作 import pymysql #1.创建链接对象c conn pymysql.Connect(host127.0.0.1,#数据库服务器主机地址port3306, #mysql的端口…

一篇文章让你了解Java中的继承

目录 继承一.什么是继承二.为什么要使用继承三.继承的语法四.继承中有重复怎么办&#xff1f;1.**访问原则** 五.super和this1.**this**2.**super**3.**super注意事项**4.**super和this异同点**六.构造方法的引入1.父类不带参数的构造方法2.父类带有参数的构造方法 七.继承中的…

【二叉树】如何构建一个包含大量随机数节点的二叉树测试用例

【二叉树】如何构建一个包含大量随机数节点的二叉树测试用例 前言一、案例准备二、自动生成随机二叉树工具类&#xff08;TreegenerateUtils&#xff09;三、如何调用随机二叉树工具类&#xff08;TreegenerateUtils&#xff09;&#xff1f; 前言 今天笔者在测试有关二叉树的…

Leetcode-206 反转链表

迭代法&#xff1a;将指针方向依次改变&#xff0c;定义两个指针pre和cur /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, Lis…

Bengio担任一作,联手一众图灵奖得主,预防AI失控,扛起AI监管大旗

图灵奖得主最近都在关心些什么呢&#xff1f;Yoshua Bengio&#xff0c;深度学习的奠基人之一&#xff0c;前几天他担任一作&#xff0c;联合多位大佬&#xff0c;发文探讨了如何在人工智能&#xff08;AI&#xff09;快速发展的时代管控相关风险&#xff0c;共同寻求当下生成式…

Flink SQL -- 命令行的使用

1、启动Flink SQL 首先启动Flink的集群&#xff0c;选择独立集群模式或者是session的模式。此处选择是时session的模式&#xff1a;yarn-session.sh -d 在启动Flink SQL的client&#xff1a; sql-client.sh 2、kafka SQL 连接器 在使用kafka作为数据源的时候需要上传jar包到…

python+requests接口自动化测试

原来的web页面功能测试转变成接口测试&#xff0c;之前大多都是手工进行&#xff0c;利用postman和jmeter进行的接口测试&#xff0c;后来&#xff0c;组内有人讲原先web自动化的测试框架移驾成接口的自动化框架&#xff0c;使用的是java语言&#xff0c;但对于一个学java&…

Linux学习之进程三

目录 进程控制 fork函数 什么是写时拷贝 进程终止 mian函数的返回值 退出码 错误码 exit() 进程等待 1.什么是进程等待&#xff1f; 2.为什么要进行进程等待&#xff1f; 3.如何进程进程等待&#xff1f; wait&#xff0c;waitpid&#xff1a; waitpid 进程替换 …

Lua更多语法与使用

文章目录 目的错误处理元表和元方法垃圾回收协程模块面向对象总结 目的 在前一篇文章&#xff1a; 《Lua入门使用与基础语法》 中介绍了一些基础的内容。这里将继续介绍Lua一些更多的内容。 同样的本文参考自官方手册&#xff1a; https://www.lua.org/manual/ 错误处理 下…

node插件MongoDB(四)—— 库mongoose 操作文档使用(新增、删除、更新、查看文档)(二)

文章目录 前言&#xff08;1&#xff09;问题&#xff1a;安装的mongoose 库版本不应该过高导致的问题&#xff08;2&#xff09;重新安装低版本 一、插入文档1. 代码2. node终端效果3. 使用mongo.exe查询数据库的内容 二、删除文档1. 删除一条2. 批量删除3. 代码 三、修改文档…

Go基础知识全面总结

文章目录 go基本数据类型bool类型数值型字符字符串 数据类型的转换运算符和表达式1. 算数运算符2.关系运算符3. 逻辑运算符4. 位运算符5. 赋值运算符6. 其他运算符运算符优先级转义符 go基本数据类型 bool类型 布尔型的值只可以是常量 true 或者 false。⼀个简单的例⼦&#…

MIPSsim模拟器 使用说明

&#xff08;一&#xff09; 启动模拟器 双击MIPSsim.exe&#xff0c;即可启动该模拟器。模拟器启动时&#xff0c;自动将自己初始化为默认状态。所设置的默认值为&#xff1a; u所有通用寄存器和浮点寄存器为全0&#xff1b; u内存清零&#xff1b; u流水寄存器为全0&#xff…

C++结构体定义 创建 赋值 结构体数组 结构体指针 结构体嵌套结构体

结构体是什么&#xff1f; struct是自定义数据类型&#xff0c;是一些类型集合组成的一个类型。结构体的定义方式 #include<iostream> using namespace std;struct Student {string name;int age;int score; };创建结构体变量并赋值 方式一&#xff0c;先创建结构体变…

基于springboot+vue开发的教师工作量管理系

教师工作量管理系 springboot31 源码合集&#xff1a;www.yuque.com/mick-hanyi/javaweb 源码下载&#xff1a;博主私 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了教师工作量管理系统的开发全过程。通过…

人工智能技术的高速发展,普通人如何借助AI实现弯道超车?

人工智能技术的高速发展&#xff0c;普通人如何借助AI实现弯道超车&#xff1f; 随着互联网信息传播的爆炸&#xff0c;人类科技文明的快速发展“人工智能”成为新的话题&#xff0c;科技的进步也让普通人觉得自己与社会脱节&#xff0c;找工作越来越难&#xff0c;创业越来越难…

Python使用Numba装饰器进行加速

Python使用Numba装饰器进行加速 前言前提条件相关介绍实验环境Numba装饰器进行加速未加速的代码输出结果 numba.jit加速的代码输出结果 前言 由于本人水平有限&#xff0c;难免出现错漏&#xff0c;敬请批评改正。更多精彩内容&#xff0c;可点击进入Python日常小操作专栏、Ope…

Aspose.OCR for .NET 2023Crack

Aspose.OCR for .NET 2023Crack 为.NET在图片上播放OCR使所有用户和程序员都可以从特定的图像片段中提取文本和相关的细节&#xff0c;如字体、设计以及书写位置。这一特定属性为OCR的性能及其在扫描遵循排列的记录时的功能提供了动力。OCR的库使用一条线甚至几条线来处理这些特…

什么是证书管理

在自带设备和物联网文化的推动下&#xff0c;数字化使连接到互联网的设备数量空前加速。在企业网络环境中&#xff0c;每个在线运行的设备都需要一个数字证书来证明其合法性和安全运行。这些数字证书&#xff08;通常称为 X.509 证书&#xff09;要么来自称为证书颁发机构 &…

长虹智能电视使用123

1、开机 在接通电源的情况下&#xff0c;长虹智能电视开机有两种方式。 方式1&#xff1a; 按电视右下角开机按钮 方式2&#xff1a; 按电视遥控器开机按钮 长虹智能电视开机后会进入其操作系统&#xff08;安卓&#xff09;。 屏幕左右双箭头图表&#xff0c;手指点击会…

力扣876:链表的中间结点

力扣876&#xff1a;链表的中间结点 题目描述&#xff1a; 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。 如果有两个中间结点&#xff0c;则返回第二个中间结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[3,4,5]…