二项堆
二项树
- 度数为 \(0\) 的二项树只包含一个结点
- 度数为 \(k\) 的二项树有一个根结点,根结点下有 \(k\) 个子树,每个子树分别是度数为 \(k-1,k-2,...,0\) 的二项树
度为 \(k\) 的二项树有 \(2^k\) 个节点,其中深度为 \(d\) 的层有 \(C_k^d\) 个节点
二项堆
二项堆是指满足以下性质的二项树的集合:
- 每棵二项树都满足小根堆性质
- 具有相同度数的二项树最多只有 \(1\) 个
包含 \(n\) 个节点的二项堆的构成情况,由 \(n\) 的二进制表示确定。第 \(i\) 位为 \(1\) 表示存在一个度为 \(i\) 的二项树,反之不存在
实现
存储
指针式存储,将每个根节点串成链表即可
合并
对于两个堆中的两个相同度数的二项树,比较树根的关键字,较大的作为较小的根节点的最左子树,时间复杂度 \(O(1)\)
对于两个堆,按度数从小到大考虑,若两个都不存在当前度数,则结果也不存在;若有一个存在,则直接放入结果中;若两个都存在,则合并为当前度数加 1 的一个新树,继续合并
将两个堆的大小的二进制表示相加,一次进位对应一次合并二项树。显然时间复杂度为 \(O(\log n)\)
插入
将新节点看做一个单独的堆,合并即可。单次 \(O(\log n)\)
查找最小关键字所在结点
显然一定在某一棵二项树的树根
\(O(\log n)\) 扫描每个树根,取最小即可
也可以保存一个指向最小元素的指针,执行其他操作时跟新,即可 \(O(1)\) 查询
删除最小关键字所在结点
找到对应的节点(树根),删去后其子树相当于一个新的二项堆,\(O(\log n)\) 合并即可。总计 \(O(\log n)\)
减小特定结点的值
和普通堆一样,向上调整即可,时间复杂度 \(O(\log n)\)
删除特定节点
将权值置无穷小,向上调整到堆顶,并删除,时间复杂度 \(O(\log n)\)
由于二项堆各操作为严格 \(O(\log n)\)(或 \(O(1)\))的,因此可以可持久化

浙公网安备 33010602011771号