优先队列(priority_queue)总结

2023-11-02


priority_queue

优先队列(priority_queue),实际上,它的本质就是一个heap,可以参考传送门
这个写的也不错

优先级队列是一个拥有权值观念的queue。它允许在底端添加元素、在顶端去除元素、删除元素。 缺省情况下,优先级队列利用一个大顶堆完成。

在这里插入图片描述
而C++STL中的优先队列就是在这个队列的基础上,把其中的元素加以排序。其内部实现是一个二叉堆。所以优先队列其实就是把堆模板化,将所有入队的元素排成具有单调性的一队,方便我们调用。

一.优先队列简介

普通的队列是一种先进先出的数据结构,元素在队列尾追加,而从队列头删除。
在优先队列中,元素被赋予优先级。当访问元素时,具有最高优先级的元素最先删除。优先队列具有最高级先出 (first in, largest
out)的行为特征。
首先要包含头文件#include, 他和queue不同的就在于我们可以自定义其中数据的优先级,让优先级高的排在队列前面,优先出队。

二.优先队列特性和操作

优先队列具有队列的所有特性,包括队列的基本操作,只是在这基础上添加了内部的一个排序,它本质是一个堆实现的。

1.头文件&定义

#include <queue>
#include <functional> //greater<>

// 定义
priority_queue<int> pq;

2.默认优先输出大数据

  • priority_queue<Type, Container, Functional>

  • 其中, Type 为数据类型. Container 为保存数据的容器. Functional 为元素比较的方式.

  • 若不写后面两个参数.

容器 默认使用 vector

比较方式 默认使用 operator < 即优先队列是大顶堆. 队头元素最大
大根堆声明方式:
大根堆就是把大的元素放在堆顶的堆。优先队列默认实现的就是大根堆,所以大根堆的声明不需要任何花花肠子,直接按C++STL的声明规则声明即可。

#include<queue>
priority_queue<int> q;
priority_queue<string> q;
priority_queue<pair<int,int> > q;

C++中的int,string等类型可以直接比较大小,所以不用我们多操心,优先队列自然会帮我们实现。但是如果是我们自己定义的结构体,就需要进行重载运算符了

(1).举例

srand(time(NULL));
priority_queue<int> pq1; // 默认是最大堆...
std::cout << "start..." << endl;
for (int i = 0; i < 10; i++) {
    int t = rand() % 100;
    cout << t << ends;
    pq1.push(t);
}
std::cout << endl;
while (!pq1.empty())
{
    cout << pq1.top() << ends;
    pq1.pop();
}
cout << endl;

输出:
在这里插入图片描述

3.优先输出小数据 即小顶堆

  • priority_queue<int, vector<int>, greater<int> > p;
  • 使用 greater<int> . 即改用 operator >
    小根堆声明方式
    大根堆是把大的元素放堆顶,小根堆就是把小的元素放到堆顶。

实现小根堆有两种方式:

第一种是比较巧妙的,因为优先队列默认实现的是大根堆,所以我们可以把元素取反放进去,因为负数的绝对值越小越大,那么绝对值较小的元素就会被放在前面,我们在取出的时候再取个反,就瞒天过海地用大根堆实现了小根堆。

第二种:

小根堆有自己的声明方式,我们记住即可(我也说不明白道理):

priority_queue<int,vector<int>,greater<int> >q;

注意,当我们声明的时候碰到两个"<“或者”>"放在一起的时候,一定要记得在中间加一个空格。这样编译器才不会把两个连在一起的符号判断成位运算的左移/右移。

(1).举例

priority_queue<int, vector<int>, greater<int>> pq2; // 最小堆

std::cout << "start..." << endl;
for (int i = 0; i < 10; i++) {
    int t = rand() % 100;
    std::cout << t << ends;
    pq2.push(t);
}
std::cout << endl;

while (!pq2.empty())
{
    cout << pq2.top() << ends;
    pq2.pop();
}
cout << endl;

结果:
在这里插入图片描述

4.自定义优先级 重载默认的 < 符号

(1).使用 funtion .
// 定义比较函数
// 后面一个表示栈顶元素? 所以这个是 "最小堆"
bool myCom(int a, int b) {
    return a % 10 > b % 10;
}

// 使用
priority_queue<int, vector<int>, function<bool(int,int)>> pq3(myCom); 

std::cout << "start..." << endl;
for (int i = 0; i < 10; i++) {
    int t = rand() % 100;
    std::cout << t << ends;
    pq3.push(t);
}

std::cout << endl;

while (!pq3.empty())
{
    cout << pq3.top() << ends;
    pq3.pop();
}
cout << endl;

输出结果:
在这里插入图片描述

(2). 自定义数据类型
#include<iostream>
#include<queue>
#include<cstdlib>
using namespace std;
struct Node{
    int x,y;
    Node(int a=0, int b=0):
        x(a), y(b) {}
};

struct cmp{
    bool operator()(Node a, Node b){
        if(a.x == b.x)  return a.y>b.y;
        return a.x>b.x;
    }
};

int main(){
    priority_queue<Node, vector<Node>, cmp>p;

    for(int i=0; i<10; ++i)
        p.push(Node(rand(), rand()));

    while(!p.empty()){
        cout<<p.top().x<<' '<<p.top().y<<endl;
        p.pop();
    }//while
    //getchar();
    return 0;

三.基本函数实现

首先函数在头文件中,归属于命名空间std,使用的时候需要注意。

priority_queue<int> q1; 
priority_queue< pair<int, int> > q2;  // 注意在两个尖括号之间 一定要留空格。 
priority_queue<int, vector<int>, greater<int> > q3; // 定义小的先出队 
1.构造函数

1.普通方法

priority_queue<int> q;                 
//通过操作,按照元素从大到小的顺序出队
priority_queue<int,vector<int>, greater<int> > q;    
//通过操作,按照元素从小到大的顺序出队

2、自定义优先级:

struct cmp {     
  operator bool ()(int x, int y)     
  {        
     return x > y;   // x小的优先级高       
     //也可以写成其他方式,
     //如: return p[x] > p[y];表示p[i]小的优先级高
  }
};

priority_queue<int, vector, cmp> q; //定义方法
//其中,第二个参数为容器类型。第三个参数为比较函数。
3、结构体声明方式:

struct node {     
  int x, y;     
  friend bool operator < (node a, node b)     
  {         
    return a.x > b.x;    //结构体中,x小的优先级高     
  }
};

priority_queue<node>q; //定义方法
//在该结构中,y为值, x为优先级。
//通过自定义operator<操作符来比较元素中的优先级。
//在重载”<”时,最好不要重载”>”,可能会发生编译错误

2.添加函数
  • q.push();插入元素到队尾 (并排序)
  • q.emplace(); 原地构造一个元素并插入队列
3.删除函数
  • q.pop();弹出队头元素
4.判断函数
  • q.empty();队列是否为空
5.大小函数
  • q.size() 返回队列内元素个数
6.其他函数
  • q.top() ;访问队头元素,返回队列首元素,不改变队列
  • swap 交换内容
7.总结

top 访问队头元素
empty 队列是否为空
size 返回队列内元素个数
push 插入元素到队尾 (并排序)
emplace 原地构造一个元素并插入队列
pop 弹出队头元素
swap 交换内容

用法 作用
q.top() 返回priority_queue的首元素
q.push() 向priority_queue中加入一个元素
q.size() 返回priority_queue当前的长度(大小)
q.pop() 从priority_queue队头删除一个元素
q.empty() 返回priority_queue是否为空,1为空、0不为空

注意:priority_queue取出队首元素是使用top,而不是front,这点一定要注意!!

代码详解

1.基本类型优先队列的例子:

#include<iostream>
#include <queue>
using namespace std;
int main() 
{
  //对于基础类型 默认是大顶堆
  priority_queue<int> a; 
  //等同于 priority_queue<int, vector<int>, less<int> > a;
  
  //   这里一定要有空格,不然成了右移运算符↓↓
  priority_queue<int, vector<int>, greater<int> > c; //这样就是小顶堆
  priority_queue<string> b;

  for (int i = 0; i < 5; i++) 
  {
    a.push(i);
    c.push(i);
  }
  while (!a.empty()) 
  {
    cout << a.top() << ' ';
    a.pop();
  } 
  cout << endl;

  while (!c.empty()) 
  {
    cout << c.top() << ' ';
    c.pop();
  }
  cout << endl;

  b.push("abc");
  b.push("abcd");
  b.push("cbd");
  while (!b.empty()) 
  {
    cout << b.top() << ' ';
    b.pop();
  } 
  cout << endl;
  return 0;
}


运行结果:
4 3 2 1 0
0 1 2 3 4
cbd abcd abc
请按任意键继续. . .

2.用pair做优先队列元素的例子:

规则:pair的比较,先比较第一个元素,第一个相等比较第二个。

#include <iostream>
#include <queue>
#include <vector>
using namespace std;
int main() 
{
  priority_queue<pair<int, int> > a;
  pair<int, int> b(1, 2);
  pair<int, int> c(1, 3);
  pair<int, int> d(2, 5);
  a.push(d);
  a.push(c);
  a.push(b);
  while (!a.empty()) 
  {
    cout << a.top().first << ' ' << a.top().second << '\n';
    a.pop();
  }
}

运行结果:
2 5
1 3
1 2
请按任意键继续. . .

3.用自定义类型做优先队列元素的例子

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

//方法1
struct tmp1 //运算符重载<
{
  int x;
  tmp1(int a) {x = a;}
  bool operator<(const tmp1& a) const
  {
    return x < a.x; //大顶堆
  }
};

//方法2
struct tmp2 //重写仿函数
{
  bool operator() (tmp1 a, tmp1 b) 
  {
    return a.x < b.x; //大顶堆
  }
};

int main() 
{
  tmp1 a(1);
  tmp1 b(2);
  tmp1 c(3);
  priority_queue<tmp1> d;
  d.push(b);
  d.push(c);
  d.push(a);
  while (!d.empty()) 
  {
    cout << d.top().x << '\n';
    d.pop();
  }
  cout << endl;

  priority_queue<tmp1, vector<tmp1>, tmp2> f;
  f.push(b);
  f.push(c);
  f.push(a);
  while (!f.empty()) 
  {
    cout << f.top().x << '\n';
    f.pop();
  }
}


运行结果:

3
2
1

3
2
1
请按任意键继续. . .

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

优先队列(priority_queue)总结 的相关文章

  • GCC C++ (ARM) 和指向结构体字段的 const 指针

    假设有一个简单的测试代码 typedef struct int first int second int third type t define ADDRESS 0x12345678 define REGISTER type t ADDRE
  • Qt - 无法让 lambda 工作[重复]

    这个问题在这里已经有答案了 我有以下功能 我想在其中修剪我的std set
  • Blazor 与 Razor

    随着 Blazor 的发明 我想知道这两种语言之间是否存在显着的效率 无论是在代码创建方面还是在代码的实际编译 执行方面 https github com SteveSanderson Blazor https github com Ste
  • 有什么工具可以说明每种方法运行需要多长时间?

    我的程序的某些部分速度很慢 我想知道是否有我可以使用的工具 例如它可以告诉我可以运行 methodA 花了 100ms 等等 或者类似的有用信息 如果您使用的是 Visual Studio Team System 性能工具 中有一个内置分析
  • Linux TUN/TAP:无法从 TAP 设备读回数据

    问题是关于如何正确配置想要使用 Tun Tap 模块的 Linux 主机 My Goal 利用现有的路由软件 以下为APP1和APP2 但拦截并修改其发送和接收的所有消息 由Mediator完成 我的场景 Ubuntu 10 04 Mach
  • Guid 应包含 32 位数字和 4 个破折号

    我有一个包含 createuserwizard 控件的网站 创建帐户后 验证电子邮件及其验证 URL 将发送到用户的电子邮件地址 但是 当我进行测试运行时 单击电子邮件中的 URL 时 会出现以下错误 Guid should contain
  • VS30063:您无权访问 https://dev.azure.com

    我正在尝试在 asp net core 2 1 mvc 应用程序中使用以下代码连接 Azure DevOps Uri orgUrl new Uri https dev azure com xxxxx String personalAcces
  • 转到 C# WPF 中的第一页

    我正在 WPF 中使用导航服务 为了导航到页面 我使用 this NavigationService Navigate new MyPage 为了返回我使用 this NavigationService GoBack 但是如何在不使用的情况
  • 是否有与 C++11 emplace/emplace_back 函数类似的 C# 函数?

    从 C 11 开始 可以写类似的东西 include
  • 两组点之间的最佳匹配

    I ve got two lists of points let s call them L1 P1 x1 y1 Pn xn yn and L2 P 1 x 1 y 1 P n x n y n 我的任务是找到它们点之间的最佳匹配 以最小化它
  • 事件日志写入错误

    很简单 我想向事件日志写入一些内容 protected override void OnStop TODO Add code here to perform any tear down necessary to stop your serv
  • C# 编译器如何决定发出可重定向的程序集引用?

    NET Compact Framework 引入了可重定向程序集引用 现在用于支持可移植类库 基本上 编译器会发出以下 MSIL assembly extern retargetable mscorlib publickeytoken 7C
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • 通过等待任务或访问其 Exception 属性都没有观察到任务的异常

    这些是我的任务 我应该如何修改它们以防止出现此错误 我检查了其他类似的线程 但我正在使用等待并继续 那么这个错误是怎么发生的呢 通过等待任务或访问其 Exception 属性都没有观察到任务的异常 结果 未观察到的异常被终结器线程重新抛出
  • 过期时自动重新填充缓存

    我当前缓存方法调用的结果 缓存代码遵循标准模式 如果存在 则使用缓存中的项目 否则计算结果 在返回之前将其缓存以供将来调用 我想保护客户端代码免受缓存未命中的影响 例如 当项目过期时 我正在考虑生成一个线程来等待缓存对象的生命周期 然后运行
  • 32位PPC rlwinm指令

    我在理解上有点困难rlwinmPPC 汇编指令 旋转左字立即然后与掩码 我正在尝试反转函数的这一部分 rlwinm r3 r3 0 28 28 我已经知道什么了r3 is r3在本例中是一个 4 字节整数 但我不确定这条指令到底是什么rlw
  • 是否有一个 C++ 库可以从 PDF 文件中提取文本,例如 PDFBox for Java? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 去年 我使用 PDFBox 在 Java 中创建了一个应用程序来获取某些 PDF 文件中的原始文本 现在
  • 过度使用委托对性能来说是一个坏主意吗? [复制]

    这个问题在这里已经有答案了 考虑以下代码 if IsDebuggingEnabled instance Log GetDetailedDebugInfo GetDetailedDebugInfo 可能是一个昂贵的方法 因此我们只想在调试模式
  • Azure函数版本2.0-应用程序blobTrigger不工作

    我有一个工作功能应用程序 它有一个 blob 输入和一个事件中心输出 在测试版中工作 随着最新的更改 我的功能不再起作用 我尝试根据发行说明更新 host json 文件 但它没有引用 blob 触发器 version 2 0 extens
  • 如何确定母版页中正在显示哪个子页?

    我正在母版页上编写代码 我需要知道正在显示哪个子 内容 页面 我怎样才能以编程方式做到这一点 我用这个 string pageName this ContentPlaceHolder1 Page GetType FullName 它以 AS

随机推荐

  • docker安装jupyter科学镜像及使用

    2020 04 03 镜像 为了方便在虚拟机上进行实验研究 本次在自己的虚拟机上安装jupyter 因为要使用jupyter 同时还要有python的环境 在docker上搜索了相关的镜像 但都是个人做的 后来发现了jupyter官方制作了
  • SQL中binary 和 varbinary的区别 blob

    http www cnblogs com lovevivi archive 2013 09 25 3339087 html binary 和 varbinary 固定长度 binary 的或可变长度 varbinary 的 binary 数
  • 查看文件的MD5 值

    从网上下载到资源文件后 为了确保下载的文件没有被黑客非法篡改 一般都会校验一下MD5是否与最初上传的版本是否一致 查看两个文件的MD5 值可以判断文件在传输过程中有没有损坏 或者丢失字节 Windows电脑 window 键盘左下角Ctrl
  • SpringBoot前后端调用接口下划线与驼峰之间转换

    1 前言 最近在开发过程中 自测自己的接口的时候 会出现一下驼峰与下划线转换问题 今天就出篇文章写下吧 顺便加深下印象 2 步骤 2 1导入maven依赖 注意 因为我的项目中引入了Redisson的依赖 所以就不用单独引入jackson依
  • 解决 Element-UI 的 el-dialog 对话框移动问题的方法

    系列文章目录 文章目录 系列文章目录 前言 一 问题描述 二 解决方法 1 安装 vuedraggable 库 2 引入并使用 vuedraggable 3 将 el dialog 放入 draggable 组件 总结 前言 Element
  • python3.8 环境下安装 robot framework 遇到的问题及解决

    博客原址 https testerhome com topics 23384 安装过程就不多说了 反正就是很心酸 以下是安装步骤 1 安装python3 8 2 在线安装robotframework pip install robotfra
  • Hyperledger fabric查询区块错误问题解决:“error Entry not found in index”

    最近写了一个Hyperledger Fabric区块监控的程序 功能是应用程序监听区块生成事件 并查询新生成区块的信息 然而 当客户端收到Peer发来的blockEvent事件后 调用Channel对象的queryBlockByNumber
  • Java面试回忆录:教你解决线上频出MySQL死锁问题!附带学习经验

    引言 最近项目上线的频率颇高 连着几天加班熬夜 身体有点吃不消精神也有些萎靡 无奈业务方催的紧 工期就在眼前只能硬着头皮上了 脑子浑浑噩噩的时候 写的就不能叫代码 可以直接叫做Bug 我就熬夜写了一个bug被骂惨了 Java并发编程技术官笔
  • 【UE4】 修改引擎-添加更多视口窗口Viewport

    先看效果 视口添加了viewport 5 和 viewport 6 前言 此修改必须基于虚幻引擎源码版 请先安装源码版虚幻引擎 源码版安装教程来自CSDN 虚幻4源码版安装 教程开始 首先安装源码版引擎 这里用的是4 26 2源码版引擎 1
  • 小米笔记本重装系统没有wifi功能和扬声器没有声音解决的过程(红米G游戏本)

    要看解决方法的直接看文章最后 经过 1 因为自己已经用pe系统给很多同学包括我自己重装过很多次系统了 所以最开始打算用pe给小米笔记本装系统 pe盘里面装的镜像是MSDN上面下载的最新1909的win10 2 最开始用pe 系统给小米笔记本
  • 初学nodejs必看,nodejs入门良言。

    断断续续用nodejs开发也快一年了 不得不说本人天资驽钝实在不敢恭维技术 只能说久病成医 坑踩的多了就知道怎么避免了 在此写写几句自己踩过的坑 希望能帮到即将步入nodejs这行的同学们 注 这篇博客技术点不多 更多的是跟大家分享一个思路
  • Java练习——输入n个数,存入数组,进行排序输出

    题目 输入n个数 存入数组 进行排序输出 package paixu import java util Scanner public class paixu public static void main String args int z
  • 数据分析常用库(包含pytorch、tensorflow安装)

    1 pandas 2 numpy 3 sklearn 安装的时候是 scikit learn 4 matplotlib 5 pytorch cuda版本pytorch安装 不一定需要更新英伟达的驱动 电脑cuda版本可以高于pytorch的
  • NSSCTF之Web篇刷题记录(13)

    NSSCTF之Web篇刷题记录 12 GXYCTF 2019 BabyUpload GKCTF 2020 cve版签到 HCTF 2018 Warmup GDOUCTF 2023 泄露的伪装 羊城杯 2020 easycon HNCTF 2
  • 服务器 风扇测试软件,图解服务器风扇安装的正确方法

    一般不是太垃圾的机箱总有两个地方可以装风扇 前面的一般在硬盘托架处 后面的一般在电源下面 键盘口上方 有的机箱出厂就已经装好1 2个风扇了 图中越红的区域温度相对越高 应该什么样的风道合理呢 1 前后都装机箱风扇的情况 应该前进后出 这样机
  • k8s搭建高可用spring-cloud-config配置中心集群

    k8s搭建高可用配置中心 查找镜像 docker部署 关闭认证方式部署 开启认证方式部署 docker compose方式部署 k8s方式部署 使用configMap挂载配置 挂载本地目录方式 测试应用加载配置中心配置启动 查找镜像 镜像地
  • Nginx禁止某IP(段)访问的两种方法

    修改Nginx配置文件nginx conf Nginx配置访问IP可以修改nginx conf文件 只需要在server中添加allow和deny的IP即可 如下 server listen 80 server name localhost
  • 数据加载的时候出现RuntimeError: Pin memory thread exited unexpectedly

    很有可能是因为num workers太大导致的 可以调小一些
  • ch03-数值计算(进阶)

    文章目录 数学函数 三角 双曲函数 指数和对数 算术操作 自动域 数值计算 舍入 和积差 符号函数 截断 插值 导数和微积分 梯度 梯形公式 多项式 简介 便捷类 关系运算 真值测试 值和类型 逻辑运算 比较 二进制运算 位运算 左右移 打
  • 优先队列(priority_queue)总结

    文章目录 priority queue 一 优先队列简介 二 优先队列特性和操作 1 头文件 定义 2 默认优先输出大数据 1 举例 3 优先输出小数据 即小顶堆 1 举例 4 自定义优先级 重载默认的 lt 符号 1 使用 funtion