最小堆

堆 堆排序 优先队列 图文详解(Golang实现)

ぐ巨炮叔叔 提交于 2019-12-06 08:25:20
引入 # 在实际应用中,我们经常需要从一组对象中查找 最大值 或 最小值 。当然我们可以每次都先排序,然后再进行查找,但是这种做法效率很低。哪么有没有一种特殊的数据结构,可以高效率的实现我们的需求呢,答案就是 堆(heap) 堆分为最小堆和最大堆,它们的性质相似,我们以最小堆为例子。 最小堆 # 举例 # 如上图所示,就为一个最小堆。 特性 # 是一棵完全二叉树 如果一颗二叉树的任何结点,或者是树叶,或者左右子树均非空,则这棵二叉树称做满二叉树(full binary tree) 如果一颗二叉树最多只有最下面的两层结点度数可以小于2,并且最下面一层的结点都集中在该层最左边的连续位置上,则此二叉树称做完全二叉树(complete binary tree) 局部有序 最小堆对应的完全二叉树中所有结点的值均不大于其左右子结点的值,且一个结点与其兄弟之间没有必然的联系 二叉搜索树中,左子 < 父 < 右子 存储结构 # 由于堆是一棵完全二叉树,所以我们可以用顺序结构来存储它,只需要计算简单的代数表达式,就能够非常方便的查找某个结点的父结点和子节点,既避免了使用指针来保持结构,又能高效的执行相应操作。 Copy 结点i的左子结点为2xi+1,右子结点为2xi+2 结点i的父节点为(i-1)/2 数据结构 # Copy // 本例为最小堆 // 最大堆只需要修改less函数即可 type

堆 堆排序 优先队列 图文详解(Golang实现)

扶醉桌前 提交于 2019-12-05 22:17:04
引入 在实际应用中,我们经常需要从一组对象中查找 最大值 或 最小值 。当然我们可以每次都先排序,然后再进行查找,但是这种做法效率很低。哪么有没有一种特殊的数据结构,可以高效率的实现我们的需求呢,答案就是 堆(heap) 堆分为最小堆和最大堆,它们的性质相似,我们以最小堆为例子。 最小堆 举例 如上图所示,就为一个最小堆。 特性 是一棵完全二叉树 如果一颗二叉树的任何结点,或者是树叶,或者左右子树均非空,则这棵二叉树称做满二叉树(full binary tree) 如果一颗二叉树最多只有最下面的两层结点度数可以小于2,并且最下面一层的结点都集中在该层最左边的连续位置上,则此二叉树称做完全二叉树(complete binary tree) 局部有序 最小堆对应的完全二叉树中所有结点的值均不大于其左右子结点的值,且一个结点与其兄弟之间没有必然的联系 二叉搜索树中,左子 < 父 < 右子 存储结构 由于堆是一棵完全二叉树,所以我们可以用顺序结构来存储它,只需要计算简单的代数表达式,就能够非常方便的查找某个结点的父结点和子节点,既避免了使用指针来保持结构,又能高效的执行相应操作。 结点i的左子结点为2xi+1,右子结点为2xi+2 结点i的父节点为(i-1)/2 数据结构 // 本例为最小堆 // 最大堆只需要修改less函数即可 type Heap []int func (h Heap)

单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)

元气小坏坏 提交于 2019-12-05 17:50:21
一、基于邻接表的Dijkstra算法   如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点。使用邻接表表示,可以使用 BFS 在O(V + E)时间中遍历图的所有顶点 。这个想法是使用 BFS 遍历图的所有顶点,并使用最小堆存储尚未包括在最短路径树中的顶点(或尚未确定最短距离的顶点)。最小堆用作优先级队列,以从尚未包括的顶点集中获取最小距离顶点。对于Min Heap,诸如 extract-min 和 reduce-key 值之类的操作的时间复杂度为 O(logV)。使用邻接表表示的 Dijkstra算法时间复杂度为 O(ELogV)。 二、详细步骤   1) 创建大小为 V 的最小堆,其中 V 是给定图中的顶点数。 最小堆的每个节点都包含 顶点数 和 顶点的距离值 。   2) 以源顶点为根初始化 Min Heap(分配给源顶点的距离值为 0)。 分配给所有其他顶点的距离值为 INF(无穷大)。   3) 当“最小堆”不为空时,执行以下操作: 从“最小堆”中提取具有最小距离值节点的顶点。让提取的顶点为u。 对于u的每个相邻顶点v,检查v是否在Min Heap中。如果 v 在“最小堆”中,并且距离值大于uv 的权重加上 u 的距离值,则更新 v 的距离值。    用下面的例子来理解。 让给定的源顶点为 0

Hufffman算法

不想你离开。 提交于 2019-12-05 05:28:35
一、Huffman算法介绍   霍夫曼编码 (英语: Huffman Coding),又译为 哈夫曼编码 、 赫夫曼编码 ,是一种用于无损数据压缩的熵编码(权编码)算法。在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现几率的方法得到的,出现几率高的字母使用较短的编码,反之出现几率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。    霍夫曼树 又称 最优二叉树 ,是一种带权路径长度最短的 二叉树 。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。   前缀代码表示以一种方式分配代码(位序列),以使分配给一个字符的代码不是分配给任何其他字符的代码的前缀。 这就是霍夫曼编码如何确保在解码生成的比特流时没有歧义的地方。   让我们通过一个反例来了解前缀代码。 假设有四个字符a,b,c和d,它们对应的可变长度代码分别为00、01、0和1。由于分配给c的代码是分配给a和b的代码的前缀,因此这种编码会产生歧义。 如果压缩的比特流是0001,则解压缩的输出可以是“ cccd”或“ ccb”或“ acd”或“ ab”。   霍夫曼编码主要包括两个主要部分:   1) 根据输入字符构建霍夫曼树。

PriorityQueue源码分析

↘锁芯ラ 提交于 2019-12-05 01:31:50
PriorityQueue是从JDK1.5开始提供的新的数据结构接口,它是一种基于 优先级堆 的极大优先级队列。优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头,字符串则按字典序排列,也可以根据 Comparator 来指定,这取决于使用哪种构造方法。优先级队列不允许 null 元素。依靠自然排序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException) 优先级队列是无界的,但是有一个内部容量,控制着用于存储队列元素的数组大小。它通常至少等于队列的大小。随着不断向优先级队列添加元素,其容量会自动增加。无需指定容量增加策略的细节。 我们从源码的角度来看看 PriorityQueue是如何实现的。 建堆: PriorityQueue内部的数组声明如下: private static final int DEFAULT_INITIAL_CAPACITY = 11; /** * Priority queue represented as a balanced binary heap: the two * children of queue[n] are queue[2*n+1] and queue[2*(n+1)].

二叉堆的介绍和Java实现

蓝咒 提交于 2019-12-03 20:33:35
一、堆和二叉堆 堆,英文名称Heap,所谓二叉堆(也有直接称二叉堆为堆的), 本质上是一个完全二叉树,前面也提到过,如果树接近于完全二叉树或者满二叉树,采用顺序存储代价会小一点,因此常见的二叉堆均是顺序实现的。 按照排列的顺序可以分为最大堆和最小堆,最大堆的特征是父节点一定大于(依据情况判断是大于等于还是严格大于,数据结构归根到底还是用来使用的)子节点的数据。同样,有最大堆就会有最小堆,最小堆的 父节点数据小于其子节点的数据,因此根节点的数据是最小的。 二、二叉堆的插入和删除 来源: https://www.cnblogs.com/lbrs/p/11807252.html

【漫画】什么是外部排序?【转】

爷,独闯天下 提交于 2019-12-03 09:53:56
漫画,什么是外部排序 还记得面试现场第一篇文章【面试现场】如何判断一个数是否在40亿个整数中?发出之后,最后蛋哥说把40亿个数先进行外部排序。有读者问到,内存无法一次性加载40亿个数,如何排序? 背景 西天取经的路上,一样上演着编程的乐趣..... (互联网侦察注:160亿字节大概是16G吧,20亿int32大概8G) 置换选择 例如我们可以从12个数据读取3个存到内存中,然后从内存中选出最小的那个数放进子串p1里; 之后再从在从剩余的9个数据读取一个放到内存中,然后再从内存中选出一个数放进子串p1里,这个数必须满足比p1中的其他数大,且在内存中尽量小。 这样一直重复,直到内存中的数都比p1中的数小,这时p1子串存放结束,继续来p2子串的存放。例如(这时假设内存只能存放3个int型数据): 12个无序的int数据 读入3个到内存中,且选出一个最小的到子串p1 从内存中再次读取一个元素86 从内存中再次读取一个元素3 从内存中再次读取一个元素24 从内存中再次读取一个元素8 这个时候,已经没有符合要求的数了,且内存已满,进而用p2子串来存放,以此类推。 通过这种方法,p1子串存放了4个数据,而原来的那种方法p1子串只能存放3个数据。 (不知道堆排序的可以看下我之前写的文章:【算法与数据结构】堆排序是什么鬼?) 从12个数据中读取3个数据,构建成一个最小堆

笛卡尔树

匿名 (未验证) 提交于 2019-12-03 00:21:02
笛卡尔树是一种特殊的二叉树,其结点包含两个关键字K1和K2。首先笛卡尔树是关于K1的二叉搜索树,即结点左子树的所有K1值都比该结点的K1值小,右子树则大。其次所有结点的K2关键字满足优先队列(不妨设为最小堆)的顺序要求,即该结点的K2值比其子树中所有结点的K2值小。给定一棵二叉树,请判断该树是否笛卡尔树。 输入格式: 输入首先给出正整数N( ≤ 1000),为树中结点的个数。随后N行,每行给出一个结点的信息,包括:结点的K1值、K2值、左孩子结点编号、右孩子结点编号。设结点从0~(N-1)顺序编号。若某结点不存在孩子结点,则该位置给出 1 。 输出格式: 输出 YES 如果该树是一棵笛卡尔树;否则输出 NO 。 输入样例1: 6 8 27 5 1 9 40 -1 -1 10 20 0 3 12 21 -1 4 15 22 -1 -1 5 35 -1 -1 输出样例1: YES 输入样例2: 6 8 27 5 1 9 40 -1 -1 10 20 0 3 12 11 -1 4 15 22 -1 -1 50 35 -1 -1 输出样例2: NO 法1 提交结果 提交时间 ״̬ 分数 题目 编译器 耗时 用户 2018/5/24 21:25:05 答案正确 20 7-4 C++ (g++) 17GJ54 测试点 提示 结果 耗时 内存 0 sample 1 答案正确 128KB 1

定时任务方案大百科

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

最大堆和最小堆基本概念

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