二叉堆

码代码辛苦了就进来看看放松放松吧

删除回忆录丶 提交于 2019-12-02 04:59:34
写代码的小女孩   天冷极了,下着雪,又快黑了。这是NOIP的前夜。在这又冷又黑的晚上,一个衣衫破烂的小女孩在机房敲着代码。她从班里逃出来的时候还拿着一本算导,但是有什么用呢?那是一本很破旧的书——那么大,一向是她妈妈垫桌角的。她默写SPFA的时候,年级主任突然冲进机房,吓得她把算导都丢掉了。书叫一个学数竞捡起来拿着跑了。他说,他可以用那本书当草纸,证明切比雪夫定理。小女孩只好自己写二叉堆,一双小脚冻得红一块青一块的。她面前的草纸堆得满满的,上面全是DP转移方程。这一整天,没有一个OJ让她AC一道题,她已经交了32遍采药了。   可怜的小女孩!她又冷又饿,浑身战栗地写着二叉堆。CRT显示器发出的光落在她的枯黄的长头发上,那干枯的头发打成卷儿披在肩上,看上去就像二叉树,不过她没注意这些。每个显示器里都透出光来,机房里飘着一股CPU发糊的怪味,因为这是NOIP前夜——她可忘不了这个。 她在主函数前面停了下来,蜷着趴在键盘上。她觉得更冷了。她不敢回家,因为她还没调完二叉堆,没写对一个DP方程,教练一定会骂她的。再说,换成别的数据结构,一样写不出来。这些题都太水,虽然神犇都写过题解了,但是题解上一般都只有三个字:傻X题。      她几乎绝望了。啊,哪怕一个函数不会RE,对她也是有好处的!她每写一遍程序,跑出来的结果就不一样,要是她有数据,她就知道哪一个程序是算对了的。她得不到数据了

优先队列的基本算法(使用二叉堆构建优先队列)

ⅰ亾dé卋堺 提交于 2019-12-02 02:22:56
一、介绍 堆,也是计算中一种很常用的数据结构,它以树的形式存在。 对于树的结构,因为有父节点和子节点的概念,所以一般通过父指针和子指针来实现。但是,也有一种特殊的树不需要使用指针而可以直接通过数组来实现,这种树就是完全二叉树(除了最后一层不用全满,其他层必须全满,而且最后一层的叶子结点都靠左对齐)。今天我们要讨论的二叉堆就是一棵完全二叉树,二叉堆也是堆的一种,只不过二叉堆拥有自己的特点,它分为最大堆和最小堆。 二叉堆特点: 最大堆:所有的父节点值都不小于其孩子节点值。(注意“其”字,仅限于当前父节点和它的子节点的比较) 最小堆:所有的父节点值都不大于其孩子节点值。(注意“其”字,仅限于当前父节点和它的子节点的比较) 算法: parent = floor(i/2),leftChild = 2*i, rightChild = 2*i+1 [注意: 存储的角标从1开始]。 二叉堆图示: 二、使用 之前的篇幅介绍过链队列和顺序队列,它们都是普通的队列,采用先进先出的方式来对元素进行操作。可是,有的时候需求并不是仅仅如此,可能会来一个优先级更高的元素操作,这个时候把它按照普通队列的方式进行处理明显是不合适的。而且,普通队列的入队和出队的时间复杂度也不是最优的。此时采用二叉堆构建优先队列,是一个折中的选择,时间复杂度是最优的,如图所示: 三、代码 定义 #include <iostream>

d-堆

天大地大妈咪最大 提交于 2019-11-29 13:47:40
二叉堆因为实现简单,因此在需要优先队列的时候几乎总是使用二叉堆。d-堆是二叉堆的简单推广,它恰像一个二叉堆,只是所有的节点都有d个儿子(因此,二叉堆又叫2-堆)。下图表示的是一个3-堆。注意,d-堆要比二叉堆浅得多,它将Insert操作的运行时间改进为。然而,对于大的d,DeleteMin操作费时得多,因为虽然树浅了,但是d个儿子中的最小者是必须找到的,如果使用标准算法,将使用d-1次比较,于是将此操作的时间提高到 。如果d是常数,那么当然两种操作的运行时间都为 O(logN)。虽然仍可以使用一个数组,但是,现在找出儿子和父亲的乘法和除法都有个因子d,除非d是2的幂,否则会大大增加运行时间,因为我们不能再通过二进制移位来实现除法和乘法了。D-堆在理论上很有趣,因为存在许多算法,其插入次数比删除次数多得多,而且,当优先队列太大不能完全装入内存的时候,d-堆也是很有用的,在这种情况下,d-堆能够以与B-树大致相同的方式发挥作用。 除了不能执行Find操作外(指以对数执行),堆的实现最明显的两个缺点是:将两个堆合并成一个堆是很困难的。这种附加的操作叫做Merge。存在许多实现堆的方法使得Merge操作的运行时间为O(logN),如下篇介绍的左式堆。 来源: https://www.cnblogs.com/linhaostudy/p/11518834.html

二叉堆【转】

南笙酒味 提交于 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

【nodejs原理&源码杂记(8)】Timer模块与基于二叉堆的定时器

人走茶凉 提交于 2019-11-28 05:37:47
【摘要】 timers模块部分源码和定时器原理 示例代码托管在: http://www.github.com/dashnowords/blogs 一.概述 Timer 模块相关的逻辑较为复杂,不仅包含JavaScript层的实现,也包括C++编写的与底层 libuv 协作的代码,想要完整地看明白是比较困难的,本章仅以 setTimeout 这个API的实现机制为主线,讲述源码中的JavaScript相关的实现部分,这部分只需要一些数据结构的基本知识就可以理解。 二. 数据结构 setTimeout 这个API的实现基于两类基本数据结构,我们先来复习一下相关的特点。对数据结构知识比较陌生的小伙伴可以参考 【野生前端的数据结构基础练习】 系列博文自行学习,所有的章节都有示例代码。 2.1 链表 链表是一种物理存储单元上非连续的存储结构,存储元素的逻辑顺序是由链表中的指针链接次序来决定的。每一个节点包含一个存放数据的数据域和存放下一个节点的指针域(双向链表中指针数量为2)。链表在插入元素时的时间复杂度为 O(1) (因为只影响插入点前后的节点,无论链表有多大),但是由于空间不连续的特点,访问一个未排序链表的指定节点时就需要逐个对比,时间复杂度为 O(n) ,比数组结构就要慢一些。链表结构也可以根据指针特点分为 单向链表 , 双向链表 和 循环链表 , Timer 模块中使用的链表结构就是