左偏树(可并堆)
link to cnblogs
入门
1. 基本要素
-
定义“外结点”表示左儿子或右儿子为空的结点
-
定义
dis_u 表示结点u 到最近的一个“外结点”的距离
2. 基本性质及结论
-
左偏树本质为小根堆,满足一个结点的权值大于等于其左右儿子的权值
-
左偏树满足左偏的性质,即对于任意一个结点
u ,满足dis_{l_u}\ge dis_{r_u} -
由于有
dis_{l_u}\ge dis_{r_u} ,因此一定有dis_u=dis_{r_u} + 1 -
定义有
n 个结点的左偏树的根为rt ,满足dis_{rt} 是\log n 级别的 -
一个
dis_{rt}=n 的左偏树,其结点数至少为2^{n + 1} - 1 (此时为满二叉树)
3. 基本操作
① 合并 (merge)
左偏树最关键的就在它的合并操作上
定义
我们先来考虑一下普通的小根堆怎么合并
首先,如果有
接着,我们将
重复上述操作,直到当
这样合并,最坏情况下是
因此,我们需要优化,一种是每次随机选择左右儿子;另一种就是采用左偏树,能够每次都稳定在
因为
② 新增结点
将这个结点当成树,进行合并操作即可
③ 求最小值并删除
堆顶就是最小值;删除即将左右儿子合并即可
记得删除后要将原来的堆顶结点清空!
④ 求结点所在的树的根节点
我们可以记录每个结点的父亲,然后一直向上跳。但显然,这样的复杂度是不对的
我们考虑用路径压缩,直接指向根节点
在合并时,我们将
再删除时,我们要使
代码