堆
-
二叉堆:
-
右数组建立的堆,在任意位置i上,左节点为2i,右节点为2i+1,父亲在i/2上, 数组的0位置为空的前提,否则是2i+1,2i+2
-
小顶堆堆中的每一个节点小于他的儿子,根节点没有父亲。大顶堆每一个节点大于他儿子节点
-
-
插入要求:尾部插入,然后调整堆,直到这个堆顺序稳定
-
调整的过程使得小元素不断往上冒,这种策略称为上滤
-
由于堆是使用数组,所以当容量饱和时候,需要进行扩展,就像ArrayList进行1.5倍扩展
-
先不急着插入尾部,用该值与他爹比较先,寻找到最佳位置插入,减少交换可提高效率
-
注意到达根节点的边界,计数器记得++;
-
-
删除操作:
-
锁定第一个值和数组最后一个;由于删除使得计算器减少一个,第一个元素置空;
-
然后将最后一个继续从根向下调整堆结构;寻找可放进去的位置这个策略叫做下滤
-
避免频繁的交换,采用:
-
定义变量temp存储最后一个元素,且放在第一个位置
-
定义循环,找出根的儿子节点最小值在做还是右,再将这个最小值和根比较
-
如果根小,那么就停值循环
-
如果根是个大值,那么将小的儿子替换掉父亲,
-
然后儿子那个方向循环,也就是,那个儿子做根
-
-
小顶堆的最小值在根节点,最大值在所有叶子节点之中(接近一半的元素)
-
构建堆:
-
寻找最后的一个非叶子节点,也就是长度的一半开始
-
通过交换保持父亲节点拥有最小值,而且还需要下滤避免子节点的儿子中有比子节点更小的
-
直到节点到达根部
-
-
优先队列的应用
-
选择问题:
-
寻找第k大的元素
-
先排序再寻找
-
维持k大小的集合,建立成k大小堆结构,当插入新值时,只需和堆顶比较,判断是否替换堆顶,替换后需要下滤调整堆结构
-
类似快排的算法,通过比较舍弃,不断靠近k-1位置;
-
创建堆后,删除k-1次堆顶后,堆顶元素就是要寻找的值
-
d-堆:d个子树的堆,是二叉堆的一种推广,在实践中4-堆胜过二叉堆,但是难合并(merge)
-
左式堆:非理想中的平衡,实际趋势非常不平衡
-
零路径长(npl):节点X儿子的最短路径,只有一个儿子就或没有儿子0;两个儿子就1;如果null就-1
-
无法使用数组表示,因为不平衡,所有高级支合并的数据结构都是使用链式储存
-
性质:对于堆中的每一个节点,左儿子的npl至少和右儿子相等或大于
-
左式堆趋向加深左路径,(在实际上更便于合并操作)
-
定理:在右路径上有r个节点的左式树必然至少有2^r-1个节点
-
左式堆是递归威力的完美实例
-
每个结点中需要有一个指示npl的项
-
左式堆操作:
-
基本操作是合并(merge),插入只是合并的一个特殊情形 。合并之后也是个左式堆;如果插入在右边,那么需要左右子树交换
-
-
删除:除去根节点得到两个堆,再将两个堆合并
-
斜堆:是左式堆的自调节形式(是一种代表缺少平衡原则的数据结构)
-
斜堆是具有堆排序的二叉树,但不存在对树结构的限制
-
不保留npl
-
基本操作还是合并
-
相对于左式堆的合并,斜堆不需要判断是否满足左式堆而进行交换操作
-
除了右路径上最后节点外,所有节点都将他们的儿子进行交换这种交换
-
二项队列
-
指出一种简单的想法如何能够用来达到好的时间界
-
堆序的树的集合,也就是森林
-
每一棵堆序树都有约束的形式:二项树
-
每一个高度至多存在一棵二项树
-
高度为0的数是单节点,而高度为k是把高度为k-1的树接到高度为k-1上
-
二项树操作
-
最小元可以通过搜索所有树的根来找出
-
合并:将同深度的两两合并
-
插入就是与单节点树合并
-
删除最小:把最小元的那棵树的根节点删除,儿子们成为各个独立的树,再和其他合并
-
标准库中优先队列 PriorityQueue
浪波激泥