最小堆

优先队列实现最小堆

匿名 (未验证) 提交于 2019-12-02 23:57:01
最小堆可是在遍历后,保存最大的k个值 最大堆可是在遍历后,保存最小的k个值 优先队列 默认为最大堆,即输出为最大值 优先队列实现最小堆 #include <iostream> #include <algorithm> #include <vector> using namespace std ; //为自定义类 做比较函数 struct cmp { bool operator ()( node a , node b ){ return a . key > b . key ; } }; int main (){ priority_queue < node , vector <node> , cmp > q ; //非自定义类 直接用greater<> priority_queue < int , vector <int> , greater <int> > q ; return 0 ; } 来源:51CTO 作者: mwb1995 链接:https://blog.csdn.net/mwb1995/article/details/89059778

数据结构中的堆(Heap)

泪湿孤枕 提交于 2019-12-02 12:06:22
来源: https://www.jianshu.com/p/6b526aa481b1 堆 就是用 数组 实现的 二叉树 ,所有它没有使用父指针或者子指针。 堆根据“堆属性”来排序,“堆属性”决定了树中节点的位置。 堆的常用方法: 构建 优先队列 支持 堆排序 快速 找出一个 集合中的最小值 (或者 最大值 ) 在朋友面前装逼 堆属性 堆分为两种: 最大堆 和 最小堆 ,两者的差别在于节点的排序方式。 在 最大堆 中, 父节点 的值比 每一个子节点 的值 都要大 ; 在 最小堆 中, 父节点 的值比 每一个子节点 的值都要 小 。 这就是所谓的“ 堆属性 ”,并且这个属性对堆中的 每一个节点 都成立。 例子: 这是一个 最大堆 ,因为 每一个 父节点 的值都 比其 子节点 要大 。 10 比 7 和 2 都大。 7 比 5 和 1 都大。 根据这一属性,那么最大堆总是将其中的 最大值 存放在树的 根节点 。而对于最小堆,根节点中的元素总是树中的最小值。 堆属性非常的有用,因为堆常常被当做 优先队列 使用,因为可以快速的访问到 “最重要”(优先级高) 的元素。 注意: 堆的根节点中存放的是最大或者最小元素,但是 其他节点的排序顺序 是 未知 的。例如,在一个 最大堆 中,最大的那一个元素总是位于 index 0 的位置,但是 最小的元素 则 未必是 最后一个元素。--唯一能够保证的是

定时任务方案大百科

霸气de小男生 提交于 2019-12-01 07:42:00
原文地址: https://crossoverjie.top 前言 节前有更新一篇定时任务的相关文章 《延时消息之时间轮》 ,有朋友提出希望可以完整的介绍下常见的定时任务方案,于是便有了这篇文章。 Timer 本次会主要讨论大家使用较多的方案,首先第一个就是 Timer 定时器,它可以在指定时间后运行或周期性运行任务;使用方法也非常简单: 这样便可创建两个简单的定时任务,分别在 3s/5s 之后运行。 使用起来确实很简单,但也有不少毛病,想要搞清楚它所存在的问题首先就要理解其实现原理。 实现原理 定时任务要想做到按照我们给定的时间进行调度,那就得需要一个可以排序的容器来存放这些任务。 在 Timer 中内置了一个 TaskQueue 队列,用于存放所有的定时任务。 其实本质上是用数组来实现的一个 最小堆 ,它可以让每次写入的定时任务都按照执行时间进行排序,保证在堆顶的任务执行时间是最小的。 这样在需要执行任务时,每次只需要取出堆顶的任务运行即可,所以它取出任务的效率很高为 。 结合代码会比较容易理解: 在写入任务的时候会将一些基本属性存放起来(任务的调度时间、周期、初始化任务状态等),最后就是要将任务写入这个内置队列中。 在任务写入过程中最核心的方法便是这个 fixUp() ,它会将写入的任务从队列的中部通过执行时间与前一个任务做比对,一直不断的向前比较。 如果这个时间是最早执行的

leetcode 347. 前 K 个高频元素 java

让人想犯罪 __ 提交于 2019-12-01 02:51:21
题目: 给定一个非空的整数数组,返回其中出现频率前 k 高的元素。 示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2: 输入: nums = [1], k = 1 输出: [1] 说明: 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。 解题: 首先遍历数组,并且用hashMap保存元素出现的次数,然后使用最小堆保存出现频率最高的K个元素 class Solution { public List<Integer> topKFrequent(int[] nums, int k) { // 使用HashMap,统计每个元素出现的次数,元素为键,元素出现的次数为值 HashMap<Integer,Integer> map = new HashMap(); for(int num : nums){ if (map.containsKey(num)) { map.put(num, map.get(num) + 1); } else { map.put(num, 1); } } // 遍历map,用最小堆保存频率最大的k个元素 PriorityQueue<Integer> pq = new PriorityQueue<>(new

找出其中最小的K个数

只愿长相守 提交于 2019-11-29 12:30:54
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。 思路: 大小为 K 的最小堆 复杂度:O(NlogK) + O(K) 特别适合处理海量数据 应该使用大顶堆来维护最小堆,而不能直接创建一个小顶堆并设置一个大小,企图让小顶堆中的元素都是最小元素。 维护一个大小为 K 的最小堆过程如下:在添加一个元素之后,如果大顶堆的大小大于 K,那么需要将大顶堆的堆顶元素去除。 public ArrayList<Integer> GetLeastNumbers_Solution(int[] nums, int k) { if (k > nums.length || k <= 0) return new ArrayList<>(); PriorityQueue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> o2 - o1); for (int num : nums) { maxHeap.add(num); if (maxHeap.size() > k) maxHeap.poll(); } return new ArrayList<>(maxHeap); } 来源: https://my.oschina.net/u/3973793/blog/3105824

二叉堆【转】

南笙酒味 提交于 2019-11-29 12:13:36
什么是二叉堆? 二叉堆是一种特殊的堆。具有如下的特性: 具有完全二叉树的特性。 堆中的任何一个父节点的值都大于等于它左右孩子节点的值(最大堆),或者都小于等于它左右孩子节点的值(最小堆)。 这个为最大堆: 这个为最小堆: 我们把二叉堆的根节点称之为堆顶。根据二叉堆的特性,堆顶要嘛是整个堆中的最大元素,要嘛是最小元素。 不过这里需要注意的是,在二叉堆这种结构中,对于删除一个节点,我们一般删的是根节点。 假设"第一个元素"在数组中的索引为 0 的话,则父节点和子节点的位置关系如下: 索引为i的左孩子的索引是 (2*i+1); 索引为i的右孩子的索引是 (2*i+2); 索引为i的父结点的索引是 floor((i-1)/2); 假设"第一个元素"在数组中的索引为 1 的话,则父节点和子节点的位置关系如下: 索引为i的左孩子的索引是 (2*i); 索引为i的右孩子的索引是 (2*i+1); 索引为i的父结点的索引是 floor(i/2); 二叉堆的图文解析 在前面,我们已经了解到:"最大堆"和"最小堆"是对称关系。这也意味着,了解其中之一即可。本节的图文解析是以"最大堆"来进行介绍的。 二叉堆的核心是"添加节点"和"删除节点",理解这两个算法,二叉堆也就基本掌握了。下面对它们进行介绍。 1. 添加 假设在最大堆[90,80,70,60,40,30,20,10,50]种添加85

最大堆和最小堆基本概念

早过忘川 提交于 2019-11-29 11:20:53
堆和栈的区别: 一、堆栈空间分配区别:   1、栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;   2、堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。 二、堆栈缓存方式区别:   1、栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放;   2、堆是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。    三、堆栈数据结构区别:   堆(数据结构):堆可以被看成是一棵树,如:堆排序;   栈(数据结构):一种先进后出的数据结构。 最大堆和最小堆是二叉堆的两种形式。 最大堆:根结点的键值是所有堆结点键值中最大者,且每个结点的值都比其孩子的值大。 最小堆:根结点的键值是所有堆结点键值中最小者,且每个结点的值都比其孩子的值小。 堆树的定义如下 : (1)堆树是一颗完全二叉树; (2)堆树中某个节点的值总是不大于或不小于其孩子节点的值; (3)堆树中每个节点的子树都是堆树。 当父节点的键值总是大于或等于任何一个子节点的键值时为最大堆。 当父节点的键值总是小于或等于任何一个子节点的键值时为最小堆。如下图所示,左边为最大堆,右边为最小堆。 具体代码实现参考以下链接:

剑指offer 数据流中的中位数

99封情书 提交于 2019-11-28 08:53:01
题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。 思路:利用两个优先队列,最大堆始终保存前一半数据,最小堆始终保存后一半数据,当两个优先队列长度一样时,将数压入最小堆。 1 class Solution { 2 priority_queue<int, vector<int>, less<int> > p; //最大堆 3 priority_queue<int, vector<int>, greater<int> > q; //最小堆 4 public: 5 void Insert(int num) 6 { 7 //偶数个,应该压入最小堆 8 if (((p.size() + q.size()) & 1) == 0) { 9 if (p.size() > 0 && num < p.top()) { 10 int temp = p.top(); 11 p.pop(); 12 p.push(num); 13 q.push(temp); 14 } else { 15 q.push(num); 16 } 17 } else { //奇数个

转:哈夫曼树详解

故事扮演 提交于 2019-11-28 03:41:01
转载至: https://blog.csdn.net/guoweimelon/article/details/50904321 一、哈夫曼树的定义   (1)简单路径长度   所谓树的简单路径长度,是指从树的根结点到每个结点的路径长度之和。   完全二叉树是简单路径长度最小的二叉树   (2)加权路径长度     所谓树的加权路径长度,是指树中所有带权(非0)叶节点的加权路径长度之和。     如下图所示,不同的树结构,加权路径长度也不一样。          1:WPL=1* 4 +2* 4 +3* 3 +4* 2 +5* 1 =34 (加粗为路径长度)     2:WPL=5* 4 +4* 4 +3* 3 +2* 2 +1* 1 =50     3:WPL=1* 3 +2* 3 +3* 2 +4* 2 +5* 2 =33   (3)哈夫曼树的定义     哈夫曼树又称最优二叉树。哈夫曼树是指 具有相同结点的树中,加权路径长度最小 的二叉树。 二、哈夫曼树的构造过程   哈夫曼树的构造过程需要借助最小堆算法。   如下图所示,首先将原始数据构造出一个最小堆,然后每次从堆中选取值最小两个节点,计算他们的权重之和,作为一个新结点的值,然后插入到最小堆中,直到所有数据结点都构造完毕,成为一个最大堆。    三、哈夫曼树的作用(哈夫曼编码)     哈夫曼编码是一种编码方式

树-哈夫曼树(Huffman Tree)

你离开我真会死。 提交于 2019-11-26 14:57:14
概述 哈夫曼树:树的带权路径长度达到最小。 构造规则 1 . 将w 1 、w 2 、…,w n 看成是有n 棵树的森林(每棵树仅有一个结点); 2 . 在森林中选出根结点的权值最小的两棵树进行合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和; 3 . 从森林中删除选取的两棵树,并将新树加入森林; 4 . 重复(02)、(03)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。 基本操作 定义 1 权值 2 左孩子 3 右孩子 4 父节点 构造哈夫曼树(使用最小堆) 1 构造最小堆; 2 进入for循环: (01) 首先,将最小堆中的最小节点拷贝一份并赋值给left,然后重塑最小堆(将最小节点和后面的节点交换位置,接着将"交换位置后的最小节点"之前的全部元素重新构造成最小堆); (02) 接着,再将最小堆中的最小节点拷贝一份并将其赋值right,然后再次重塑最小堆; (03) 然后,新建节点parent,并将它作为left和right的父节点; (04) 接着,将parent的数据复制给最小堆中的指定节点。 转载于:https://www.cnblogs.com/lucas-hsueh/p/3736772.html 来源: https://blog.csdn.net/weixin_30635053/article/details/98904046