堆Heap和优先队列(Priority Queue)学习小结

STL(主要函数及时间复杂度) vector、map、queue 等 C++ 常用 STL的特性、函数时间复杂度和用法。 阅读详情

Heap是一种数据结构,能保证取max/min是O(1)时间。通常如果查最小值/最大值,我们可以用Heap。如果是查是不是存在(Contain()),就用HashMap。如果又要查最小/大值,又要查是不是存在,就用Heap+HashMap.

Max-heap/Min-heap保证父节点都比子节点大/小,但兄弟节点之间没有大小关系。

Heap虽然是一个(满)二叉树,但通常用数组实现(因为容易实现)。一个节点i的左子节点编号是2*i,右子节点是2*i+1。Heap通常是完全二叉树(因为效率高),但没有要求一定是完全二叉树。

Heap Sort就是把所有元素放到Max Heap或Min Heap里面,再一个一个pop出来。时间复杂度最坏/最好/平均 都是O(nlogn),空间复杂度为O(1)。注意Heap Sort是不稳定排序,因为它不能保证重复元素排序后还保留前后一致的顺序。注意Heap Sort实际应用不多,为什么呢?因为Heap的维护很麻烦。实际场景中的数据是频繁发生变动的,而对于待排序序列的每次更新(增,删,改),我们都要重新做一遍堆的维护,以保证其特性(父节点大/小于其子节点),这在大多数情况下都是没有必要的。
另一个原因是Heap的cache locality不好,即如果在较短时间内访问多个元素,这多个元素在Heap中的位置可能较远,所以不能用cache一次读出来。
当数据更新不很频繁的时候,堆排序可能会比较实用。

Priority Queue也是一种数据结构。其中每个元素都有一个关键字key,元素之间的比较都是通过key来比较的。优先队列包括最大优先队列和最小优先队列,优先队列的应用比较广泛,比如作业系统中的调度程序,当一个作业完成后,需要在所有等待调度的作业中选择一个优先级最高的作业来执行,并且也可以添加一个新的作业到作业的优先队列中。一个典型的例子是实时输出最近的一个小时内访问频率最高的10个IP 。注意这里是实时输出,也就是说Priority Queue/Heap可以用于在线算法,不需要读完全部的数据,可以real time输出到当前为止的结果。

Priority Queue可以用Heap实现,也可以用其他方式,比如说直接对数组插入实现,但是效率不高。注意Priority Queue不是Queue,那为什么它的名字里面有queue呢?可能是因为它能提供queue的接口,比如remove(),pop(), insert(), top()等等。

Priority Queue和Heap有什么区别吗?如果是JAVA自带的Priority Queue的话,答案是有的(C++的Priority Queue可能也类似,具体要确认一下)。
具体的区别是在remove操作中,Priority Queue的时间复杂度是O(n),而Heap是O(logn)。因为Priority Queue需要找到这个数据,需要O(n)的时间,而Heap借助了HashMap,所以只需要O(1)的时间就可以找到。那为什么Priority Queue不用HashMap呢?这个就是JAVA提供的函数里面没有加上这一块而已,如果自己编程就也可以是O(logn)。

C++的priority_queue的定义是:
priority_queue<Type, Container, Functional>
Type为数据类型, Container为保存数据的容器,Functional为元素比较方式。

如果不写后两个参数,那么容器默认用的是vector,比较方式默认用operator<,也就是优先队列是大顶堆,队头元素最大。

下面的内容参考了链接
https://blog.youkuaiyun.com/nisxiya/article/details/45725857

另外,需要注意的是,C++ STL默认的priority_queue是将优先级最大的放在队列最前面,也即是最大堆。
假设有如下一个struct:

struct Node {
    int value;
    int idx;
    Node (int v, int i): value(v), idx(i) {}
    friend bool operator < (const struct Node &n1, const struct Node &n2) ; 
};

inline bool operator < (const struct Node &n1, const struct Node &n2) {
    return n1.value < n2.value;
}

priority_queue<Node> pq; // 此时pq为最大堆

如果需要最小堆,则需要如下实现:

struct Node {
    int value;
    int idx;
    Node (int v, int i): value(v), idx(i) {}
//  friend bool operator < (const struct Node &n1, const struct Node &n2) ;
    friend bool operator > (const struct Node &n1, const struct Node &n2) ;
}; 

inline bool operator > (const struct Node &n1, const struct Node &n2) {
    return n1.value > n2.value;
}
priority_queue< Node, vector< Node >, greater< Node > > pq; // 此时greater会调用 > 方法来确认Node的顺序,此时pq是最小堆

注意为什么greater是最小堆呢,而less是最大堆呢?因为如果是greater的时候,说明大的会沉下去,所以是最小堆。如果是less
priority_queue<int, vector<int>, greater<int>> minHeap;
priority_queue<int, vector<int>, less<int>> maxHeap;

也可以用以下办法定义最小堆:

class Node {
public:
    Node(int r, int c, int v) : row(r), col(c), val(v) {}
    bool operator < (const Node & obj) const {
        return val > obj.val;
    }
    int row, col, val;
};
priority_queue<Node> pq;

注意:我们什么时候需要定义operator<和operator>呢?这里要注意最小堆需要跟top比,比top大的才能进堆,所以需要定义operator>,同理,最大堆需要定义operator<。但如果这里我们不用自定义类型(比如Node)的话,我们就不需要定义operator<和operator>了,因为C++可以直接对内部保留类型(如int, char)来比大小。

也可以用decltype来定义最大堆和最小堆。以最小堆为例:

  map<int, int> freqs; //<num, freq>
 int n = nums.size();
 for (int i = 0; i < n; i++) {
     freqs[nums[i]]++;
 }
 auto comp = [&](int a, int b){return freqs[a] > freqs[b];};
 priority_queue<int, vector<int>, decltype(comp)> minHeap(comp);

记忆捷径:把 return a > b 翻译成“排序”如果你觉得底层的堆推导很绕,可以用 std::sort 的逆向思维来记忆:在 std::sort 中,如果你传入 a > b,代码会按从大到小降序排列(大元素在前面)。std::priority_queue 的堆顶,对应的是底层数组的“末尾”(因为为了效率,pop 操作是从数组末尾移除元素的)。如果数组是从大到小排列(大…中…小),那么末尾就是最小的元素。既然末尾是最小的元素,而堆顶对应的就是末尾,那么堆顶自然就是最小的元素(小顶堆)。
末尾是最小的元素,而堆顶对应的就是末尾。为什么? 这是一个非常硬核且底层的 C++ 标准库(STL)实现细节。简单直接的答案是:为了实现 (O(1)) 时间复杂度的删除(Pop)操作。如果堆顶对应数组的开头(索引 0),删除堆顶时就需要移动数组中的所有其他元素,这会导致性能暴跌。为了避免这个性能问题,C++ STL 的 std::priority_queue 巧妙地利用了 std::vector 的末尾。:

注意:sort()和priority_queue<> 的第3个参数不一样!sort不用加decltyp,priority_queue要加。
它们两个的第三个参数本质完全不同:std::sort 是一个函数(Function),它的第三个参数需要传入一个对象 / 实例(可调用对象)。std::priority_queue 是一个类模板(Class Template),它的第三个参数需要传入一个类型(Type)。这就是为什么一个不需要 decltype,而另一个必须要加(或者传入结构体)的原因。

另外,一个诀窍关于记住第3个参数到底是类型type还是实例。

  1. container(e.g., map, set, queue, priority_queue, vector, …) 的第3个参数是type; function(e.g., sort)的第3个参数是function。
    注意:仿函数是一个类,仿函数的实例相当于一个function。Lambada函数也相当于一个function。

//这是一个仿函数,因为重载了operator()
//注意对unordered_map和unordered_set,这里opeator()要返回size_t。对map,set,priority_queue,sort,这里operator()要返回bool
struct Compare {
bool operator()(const Node& a, const Node& b) const {
return a.dist < b.dist;
}
};
//这是仿函数的实例, 另外Compare()或者Compare{}也是仿函数的实例
Compare compare;
sort(nodes.begin(), nodes.end(), compare); //注意,如果是priority_queue,第3个参数就用Compare就行了.
临时仿函数实例
sort(nodes.begin(), nodes.end(), Compare{});
Lambda 实例
sort(nodes.begin(), nodes.end(),
[](const Node& a, const Node& b) {
return a.dist < b.dist;
});
Lambda 表达式产生的也是一个匿名类的对象,该类重载了 operator()。

  1. 看符号:
    尖括号 < >(如 map<…>, unordered_map<…>, priority_queue<…>),里面一律填 类型(Type)。
    圆括号 ( )(如 sort(…), find_if(…)),里面一律填 对象/值(Object/Value)。

如果硬要用 Lambda:
传给尖括号 < >:必须写 decltype(your_lambda)(C++20 之前)。
传给圆括号 ( ):直接写 your_lambda 名字或者把 { … } 丢进去即可。

/////////////////////

  1. std::priority_queue(类模板:传类型)当你声明一个优先队列时,你是在定义一个变量(创建对象)。在 C++ 中,定义变量时尖括号 < > 里面填写的必须是编译期就能确定的“类型”。
    正确写法:第三个参数是仿函数的“类型”
priority_queue<int, vector<int>, greater<int>> pq; 

priority_queue 内部会根据你传入的类型 greater,在自己类里面实例化出一个该类型的成员变量。在后续调用 push 等操作时,它会在底层自己调用这个成员变量。
如果你想用 Lambda 函数,也必须像 unordered_map 一样使用 decltype 来获取其类型,并且还要把 Lambda 对象传给构造函数:

auto cmp = [](int a, int b) { return a > b; };

// 尖括号内填类型,小括号内填对象
priority_queue<int, vector, decltype(cmp)> pq(cmp); //cmp是Lambda函数,类型是函数。这里第3个参数要是类型,所以要加decltype.

  1. std::sort(函数模板:传对象)当你使用 std::sort 时,你是在执行一个具体的操作(调用函数)。函数的圆括号 ( ) 里面填写的必须是运行期的“对象、变量或临时值”。
vector<int> nums = {3, 1, 4};

// 正确写法 1:传入一个临时的仿函数“对象”(注意后面的小括号 {} 或 ())
sort(nums.begin(), nums.end(), greater<int>{}); 

// 正确写法 2:直接传入一个 Lambda 函数“对象”
sort(nums.begin(), nums.end(), [](int a, int b) { return a > b; });

std::sort 的第三个参数是一个可调用对象。编译器会通过自动类型推导(Template Argument Deduction),自己去识别你传进来的对象的类型,不需要你在尖括号里手动指定。

//////////////////////////////////////////////////

一个经典的用最大堆和最小堆的例子是求n个无序数中的第K大的数。该题用最大堆和最小堆都可以做 (重要!)。
用最大堆做的代码如下。复杂度O(nlogn)

    // max-heap
    int findKthLargest(vector<int> &nums, int k)
    {
        priority_queue<int> pq(nums.begin(), nums.end());
        for (int i = 0; i < k - 1; i++)
        {
            pq.pop();
        }
        return pq.top();
    }

用最小堆做代码如下。复杂度O(nlogk)

    // min-heap
    int findKthLargest(vector<int> &nums, int k)
    {
        priority_queue<int, vector<int>, greater<int> > pq;

        for (int i = 0; i < nums.size(); i++)
        {
            if (pq.size() == k)
            {
                int x = pq.top();
                if (nums[i] > x)
                {
                    pq.pop();
                    pq.push(nums[i]);
                }
            }
            else
            {
                pq.push(nums[i]);
            }
        }
        return pq.top();
    }
};

当然也可以用将乘以负数的办法来构造最小堆。比如要构造一个int类型的最小堆:

priority_queue pq; //
pq.push( -1 * v1) ; //
pq.push( -1 * v2) ; //
pq.push( -1 * v3) ; // 分别是插入v1, v2, v3变量的相反数,那么pq其实也就变相成为了最小堆

下面这个链接很不错:
https://blog.youkuaiyun.com/txl199106/article/details/44588487

另外,也可以通过定义struct cmp来实现最小堆,cmp里面只需给出operator()函数。给出operator()后则不需再定义operator < 或operator >。用这种方法必须通过以下方式定义priority_queue。

    priority_queue<Node,vector<Node>,cmp>q;

注意:priority_queue第3个参数cmp必须是class/struct,而sort()的第3个参数可以是function或class/struct的实例(注意是实例,不是class/struct的定义)。

举例如下(定义最小堆)。如果要生成最大堆,只需将operator()里面的>改成<即可。

struct node{
  int idx;
  int key;
  node(int a=0, int b=0):idx(a), key(b){}
};

struct cmp{
  bool operator()(node a, node b){
    return a.key > b.key;
  }
}; 
priority_queue<node, vector<node>, cmp> q;

实例代码如下 (from https://blog.youkuaiyun.com/txl199106/article/details/44588487):

#include <iostream>
#include <queue>
using namespace std;
struct Node{
	int x, y;
}node;
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>q;
    for(int i=0;i<10;i++){
    	node.x=i;
    	node.y=10-i/2;
		q.push(node);
    }
    while(!q.empty()){
        cout<<q.top().x<<' '<<q.top().y<<endl;
        q.pop();
    }
    return 0;
}

该代码输出如下:
0 10
1 10
2 9
3 9
4 8
5 8
6 7
7 7
8 6
9 6

如果将operator()里面的>改为<,则为最大堆。输出结果为:
9 6
8 6
7 7
6 7
5 8
4 8
3 9
2 9
1 10
0 10

另外,C++里面也可以用multiset实现最大堆和最小堆。代码如下:

    multiset<int, greater<int>> greaterSet;
    multiset<int, less<int>> lessSet;
    multiset<int> defaultSet;  //默认为lessSet

将元素插入堆后,greaterSet.begin()所指向的值就是最大值。lessSet.begin()所指向的值就是最小值。

一个小总结 (不一定对)
求第K大用最小堆:
求第K小用最大堆
这个好像不管是对动态数据和静态数据都实用,时间复杂度O(nlogk)。但静态数据求第k大/小用quickselect更好,时间复杂度O(n)。

注意:堆是完全二叉树,但不是平衡二叉树。为什么不是平衡二叉树呢?堆的左右两个子树的高度差的绝对值不超过1啊?因为平衡二叉树必须首先是binary search tree,堆不满足这个条件。

另外,下面这个链接解释了为什么sort和priority_queue的第三个参数不一样,sort是传入一个Compare类的实例,而priority_queue是传入一个类。这是因为本质上:
sort是一个函数,函数参数列表()中需要传入实例化后的具体对象;
priority_queue是一个模板类,模板的类型参数表中<>需要传入具体的类,而不是对象。
https://www.codenong.com/cs109745348/

【C++】大根堆(优先队列 priority_queue)与 小根堆 而在这个例子中,我们使用了STL自带的小根堆,因此需要将。是指底层容器的类型,而。是指比较函数对象的类型。 阅读详情

相关推荐

优先队列(Priority Queue)变种和加强

《Handbook of Data Structures and Applications》介绍了一系列针对不同需求的设计精妙的Priority Queue和参考文献。 下面包含这些Priority Queue之间的关系:   Queue 队列 (Queue) 是一个基本的数据结构。支持先进先出 (FIFO: First In First Out) 的线形表。主要支持下面两

Three Body 的专栏 3492

priority_queue用法详解

一  priority_queue常用函数实例解析 (1) push() push(x) 令x入队,时间复杂度为O(log N), 其中 N 为当前优先队列中元素的个数 (2) top() 获得队首元素(即堆顶元素),时间复杂度为O(1). (3) pop() 令队首元素(即堆顶元素)出队,时间复杂度为O(log N). (4) empty() 检测优先队列是否为空,返回 true则空,返

Grady_Ne的博客 3011

C++中的队列(queue)和优先队列(priority_queue)总结

1.queue introduction队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受

Rosun 2613

《算法笔记》6.6 priority_queue详解

6.6 priority_queue详解 priority_queue又称为优先队列,其底层是用堆来进行实现的。在优先队列中,队首元素一定是当前队列中优先级最高的那一个。 当然,可以在任何时候往优先队列里面加入(push)元素,而优先队列底层的数据结构堆会随时调整结构,使得每次的队首元素都是优先级最大的。 要使用queue,需先添加头文件和命名空间。 #include<queue> using namespace std ; 1. priority_queue的定义 priority_queu

Zhou9841的博客 1245

C++堆(优先队列)priority_queue

堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆(大根堆);每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆(小根堆)。从堆的概念可知,堆是一棵完全二叉树,因此可以使用层序的规则采用顺序的方式来高效存储。完全二叉树,我的理解:任何节点的子节点只有以下三种情况:一,没有孩子。二,有两个孩子。三,只有左孩子。不会出现只有右孩子,没有左孩子的情况。根节点的编号1,根节点的左孩子编号2,根节点的右孩子编号3。2的孩子编号为:4,5。3的孩子编号:6,7。

闻缺陷则喜何志丹 1494

微信本地数据解密实战:从AES加密原理到EnMicroMsg.db恢复指南

数据加密是保障信息安全的核心技术,其中对称加密算法AES因其高效可靠,被广泛应用于各类本地数据保护场景。其原理是通过特定密钥对数据进行混淆转换,确保未经授权者无法读取原始内容。在移动应用领域,本地数据库加密对于保护用户隐私、防止数据泄露具有重要价值。微信作为国民级应用,对其本地存储的聊天记录数据库(EnMicroMsg.db)采用了基于设备标识和用户UIN生成的AES-256-CBC加密方案。理解这一机制,不仅有助于在合法合规前提下进行个人数据备份与恢复,也为开发者进行客户端安全分析、兼容工具开发提供了基础

weixin_30764883的博客 565

堆(heap)与优先队列(priority queue)

一、堆 1.堆定义: 如果这棵完全二叉树的任意结点的关键字小于或等于其左孩子和右孩子的关键字,则称之为小堆

weixin_52575498的博客 4235

三相逆变器拓扑结构的分析及应用场景

三相逆变器是电力电子领域中广泛应用的一种设备,用于将直流电转换为交流电。不同的拓扑结构在性能、成本、复杂度和应用领域上存在差异。小编将在本文中将进一步拓展对三相逆变器拓扑结构的分析,并探讨其适用的应用场景。

道合顺的博客 2235

Python 优先队列(priority queue)和堆(heap)

队列和优先队列(Priority Queue) 队列是一种可以完成插入和删除的数据结构。普通队列是先进先出(FIFO), 即先插入的先被删除。 然而在某些时候我们需要按照任务的优先级顺序来决定出队列的顺序,这个时候就需要用到优先级队列了。优先队列是一种可以完成插入和删除最小元素的数据结构 python中有现成的优先队列类可以调用。 代码示例 from queue import Queue # ...

qq_39463274的博客 2万+

Benchmark系列——基本概念和分类

本文主要介绍了Benchmark的基本概念和分类情况。

Bluetangos的博客 8434

manimgl安装

安装manimgl

happytree001的博客 705

C++优先队列/priority_queue(最大堆、最小堆)

定义: priority_queue<int,vector,less> q;最大堆(默认为最大堆) priority_queue<int,vector,greater> q;最小堆 Priority queues are a type of container adaptors, specifically designed such that its first eleme...

geter_CS的博客 2万+

【Java】利用反射执行Spring容器Bean指定的方法,支持多种参数自动调用

目录 使用情景 目的 实现方式 前提: 思路 核心类 测试方法 使用情景 将定时任务录入数据库(这样做的好处是定时任务可视化,也可以动态修改各个任务的执行时间),通过反射执行对应的方法; 配合Netty实现简单的HTTP请求处理框架 其他需要使用反射执行Spring方法的业务亦可 目的 很多文章都提到了反射,但是对于方法参数处理这一块都是明确了类型,不支持按照实际参数动态转换,而本篇文章提供了一个思路怎么做到方法参数的动态调用。 大家也可以...

ITjianshuzhai的博客 2333

优先队列 priority_queue详解

说到,priority_queue优先队列。必须先要了解啥是堆与运算符重载(我在下方有解释)。否则只知皮毛,极易忘记==寸步难行。但在开头,还是简单的说下怎么应用。

2302_80067378的博客 1732

保姆级教学:从0搭建微信小程序SpringBoot+Vue(一)

目标:实现一个微信小程序从后端数据库MySQL获取的商品展示页。 框架:后端采用SpringBoot,前端采用Vue,数据库MySQL。 部署工具:IntelliJ IDEA 2024.2专业版+HbuilderX+Node+微信开发者工具,jdk1.8已安装

weixin_44545610的博客 4924

遗传算法(Genetic Algorithm)详解与实现

遗传算法(Genetic Algorithm, GA)是受自然进化原理启发的一系列搜索算法。通过模仿自然选择和繁殖的过程,遗传算法可以为涉及搜索、优化和学习的各种问题提供高质量的解决方案。同时,它们类似于自然进化,因此遗传算法可以克服传统搜索和优化算法遇到的一些障碍,尤其是对于具有大量参数和复杂数学表示形式的问题。

盼小辉丶的博客 24万+

Heap —— Priority Queue 【堆 / 优先队列】

前言 - 为堆的学习做准备 二叉树的顺序存储 前面所讲的二叉树,什么孩子表示法呀,还有 孩子双亲表示法啊,都是链式存储。 而现在讲的是:顺序存储一棵二叉树。   存储方式 使用数组保存二叉树结构,方式即将二叉树用层序遍历的方式放入数组中。 一般只适合表示完全二叉树,因为 非完全二叉树会有空间的浪费。【也就是说:如果使用顺序存储来存储一棵二叉树,那么,最好是完全二叉树,这样就不会有太多的空间被浪费】 这种方式的主要用法就是堆的表示。   下标关系 已知双亲(parent)的下标,则:

DarkAndGrey的博客 2078

XCP详解「3.1·ASAP2新建A2L文件」

后面是ASAP2新建A2L的操作步骤,如果是APE中新建的A2L就无需以下操作,APE只需要导入现成的A2L即可。退出点击保存时会提示保存A2L文件,是因为前面导出的是1.70版本,工程最低1.71,可以另外起个名字即可。导入elf文件,elf路径建议直接索引编译生成的Debug下的,防止编译后忘记更新。导出V1.70格式A2L文件,APE17支持V1.70。通过ASAP2生成需要A2L文件更常用些。同一个信号可以创建不同属性量。ASAP2中新建A2L文件。设置标定信号数量最大值。XCP详解「总目录」

光明磊学习&积累的地方 3059

c++中STL之heap, priority_queue使用

C++中堆的应用:make_heap, pop_heap, push_heap, sort_heap, priority_queue make_heap, pop_heap, push_heap, sort_heap都是标准算法库里的模板函数,用于将存储在vector/deque 中的元素进行堆操作,对不愿自己写数据结构堆的C++选手来说,这几个算法函数很有用,下面是这几个函数操作vecto

longhopefor,开启学习之路 1万+

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

c++ 优先队列(priority_queue)

优先队列的本质是堆,但它具有队列的所有操作特性,与普通队列不同的地方就是出队的时候按照优先级顺序出队,这个优先级即最大堆或最小堆的规则(即大的为top优先出队或小的为top优先出队),在队列的基础上加了个堆排序。以O(log n) 的效率查找一个队列中的最大值或者最小值,其中是最大值还是最小值是根据创建的优先队列的性质来决定的。

我走的每一步都算数 8792

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

STL 之 优先队列(priority_queue)

1、什么是优先队列        能够完成下列两种操作的数据结构,我们便称之为优先队列。        ①插入一个数值    ②取出最大(或者最小)的数值(获取数值,并且删除)。        从严格意义上来说优先队列,并不是队列,因为它并不遵循队列的FIFO(先进先出的原则)。 2、实现优先队列       我们可以使用一种叫做“堆(heap)”的数据结构来实现优先队列。堆有一个重要的

Enstein_Jun 1万+

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

算法竞赛里面的STL——堆和priority_queue

此外,双向链表还能迅速定位到删除操作后新相邻的元素,便于我们判断它们是否为未出列的异性,并据此更新堆中的配对信息。那我为什么不建一个大根堆,只要我保证这个堆的大小是k,这样子堆顶的元素就会一直是第k小的。由于我们使用的是大根堆,所以20是优先级最高的元素。时间复杂度:由于底层是一个堆结构,所以删除优先级最高的元素的时间复杂度为O(log n),其中n是优先级队列中的元素数量。所谓第k大,我们完全可以创建一个小根堆,然后保持堆的大小是k,然后这样子就能保证heap.top()就是第k大的元素了。

2301_80224556的博客 1423

C++ 标准模板库(STL)——priority_queue和heap的使用和底层实现

本文介绍了C++ STL中的priority_queue和heap数据结构。priority_queue是容器适配器,默认使用vector作为底层容器,通过仿函数控制排序方式(默认大顶堆)。文章讲解了priority_queue的基本操作和使用方法,并详细分析了仿函数的实现原理。随后深入探讨了heap的底层特性,包括完全二叉树结构、大/小根堆定义以及核心操作算法(向下调整、向上调整和建堆),最后给出了大根堆的C++实现代码,包含插入、删除等基本操作。这些内容为理解和使用优先级队列和堆数据结构提供了实用指导。

2501_90523001的博客 866

C++ priority_queue(优先队列)

C++priority_queue(优先队列)

qq_44955826的博客 2055

c++ heap (堆)

C++ STL中提供了不少和排序相关的算法,包括堆排序(heap_sort)、排序(sort)、稳定排序(stable_sort)、局部排序(partial_sort),时间复杂度均为O(nlogn)。其中,对于堆排序,也提供了不少函数,像入堆push_heap、创建堆make_heap、出堆pop_heap,是否为堆is_heap等。首先要明确数据结构上堆的概念。对于一个迭代器区间上的元素,不管实际的数据结构如何,都可以逻辑上排成一个完全二叉树,如果树的每个父节点都不小于左右两个子节点,那么区间元...

JIAN_ZANG1125的博客 4358

关于make_heap和priority_queue

参考文献 1.stl里关于heap的函数与priority_queue的区别 2.C++中两种实现堆的方式:make_heap和priority_queue 3.[STL]heap和priority_queue 大家都知道,priority_queue是用堆实现的,可以通过重载()运算符选择使用最大堆或最小堆。以前一直觉得stl里面的heap相关的函数都是多余的,因为一般的heap操作都可以用p...

zhuhongde的博客 1037
上一篇: LintCode-900: Closest Binary Search Tree Value
下一篇: LintCode-596: Minimum Subtree
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值