【数据结构】【OI】二项堆的原理及代码实现
来源:互联网 发布:xp系统链接网络打印机 编辑:程序博客网 时间:2024/06/16 05:12
二项堆
二项堆(Binomial Heap)是二项树(Binomial Tree)的集合,它与二叉堆、左偏树、斜堆一样,也是用来实现优先队列操作的。二项堆支持查找最小值、删除最小值、插入、删除、合并操作,每项操作时间复杂度为O(logn)(经过优化后,查找也是O(1))。为什么要学习二项堆?首先二项堆的合并操作为O(logn)的,而且它拥有时间复杂度,可以进行可持久化操作。
二项树
二项树是一组多叉树的序列,二项树满足以下性质:
- 第
k 棵树一共有2k 个节点,第0棵树有一个节点 - 第
k 棵树的第i(0,k−1) 行有Cik 个节点(节点按二项分布) - 第
k 棵树由前k−1 棵树组成 - 任意高度只有一颗树,二项树的高度称为它的度数
由以上结论,任意大小的二项堆都可以用唯一的二项树集合表示,如一个有21个节点的二项堆,可以被一个高度为5的树(节点数为16)、高度为3的树(节点数为4)、高度为1的树表示,即使用类似二进制的方式表示。
二项堆的实现
1、构造
对于每个二项堆,定义根节点为第一棵根节点的根,使用链表将每棵二项树的根连接起来(这个链表叫根链表),就得到一个完整的二项堆结构。
对于每个节点,存有其子树的度数、自身的值、Next、Fa、Son
struct Node{ int Fa,Son,Next,d,v;}T[10000];
2、查询
由于每颗二项树都满足堆的性质,所以我们用链表结构将二项树连接起来,取每棵树的最小值即可。
3、合并
合并操作是二项堆的重要也是基本操作,二项堆的插入和删除操作也在它的基础上进行,合并操作一共有两个步骤:
(1)将两个二项堆的根链表按度数从小到大顺序合在一起,得到一个未成形的二项堆
(2)将新堆中度数相同的树合并在一起,形成度数+1的新二项树(从小到大进行)
代码实现如下:
int Merge(int h1,int h2){ if(!h1)return h2; if(!h2)return h1;//防止prev访问越界 int _prev=0,heap; while(h1&&h2){ if(T[h1].d<=T[h2].d){//依次选取度数小的连接到新堆 if(_prev==0)_prev=h1,heap=h1; else T[_prev].Next=h1,_prev=h1; h1=T[h1].Next; } else { if(_prev==0)_prev=h2,heap=h2; else T[_prev].Next=h2,_prev=h2; h2=T[h2].Next; } } if(h1)T[_prev].Next=h1; else T[_prev].Next=h2; return heap;}void Link(int son,int fa){ T[son].Fa=fa; T[son].Next=T[fa].Son;//Son记录左起第一个儿子,兄弟之间形成一个链表 T[fa].Son=son; T[fa].d++;}int Union(int h1,int h2){ int heap=Merge(h1,h2); int x=heap,_prev=0,_next=T[x].Next; while(_next!=0){ if(T[x].d!=T[_next].d) _prev=x,x=_next;//度数不相同,不需要合并 else if(T[x].v<=T[_next].v){ T[x].Next=T[_next].Next; Link(_next,x);//度数相同,将较大的树连接到小树上 } else { if(_prev==0)heap=_next; else T[_prev].Next=_next; Link(x,_next); x=_next; } _next=T[x].Next; } return heap;}
4、插入
将插入的节点看作一个堆与原堆进行合并即可
5、删除最小值
在根链表中找到这个节点,将其在链表中删除,并将其子节点链表反序,作为一个新堆与原堆合并
int Delete(int h){ int heap=h,Minn=GetMin(h),_prev=0,_next; while(T[h].v!=Minn)_prev=h,h=T[h].Next; if(_prev)T[_prev].Next=T[h].Next; else heap=T[h].Next;//链表的删除 T[h].Next=0,h=T[h].Son; T[h].Fa=0; _prev=0; while(T[h].Next){ _next=T[h].Next; T[h].Next=_prev; _prev=h,h=_next; }//节点链表反序 T[h].Next=_prev; heap=Union(h,heap);//重新合并 return heap;}
6、可持久化
等我研究出了再更新吧=_=
阅读全文
1 0
- 【数据结构】【OI】二项堆的原理及代码实现
- 数据结构 哈希表的原理和代码实现
- Java数据结构及原理实现
- autolayout的使用原理及代码实现
- 订单的处理原理及代码实现.
- 二分查找的原理及代码实现
- 数据结构 跳表SkipList的原理和代码实现
- 【数据结构】链表的原理及java实现
- 【数据结构】堆栈、队列的原理及java实现
- 【数据结构】二叉树的原理及实现学习总结
- 【数据结构】链表的原理及java实现
- 【数据结构】链表的原理及java实现
- TrieTree字典树数据结构的原理、实现及应用
- 【数据结构】链表的原理及java实现
- UPNP的工作原理及详细过程及代码实现
- 数据结构的代码实现
- BatchNormalization 原理及代码实现
- 数据结构 线索二叉树 原理及实现
- Java之多线程CountDownLatch 用法 -yellowcong
- 练习题(基础练习)
- MyBatis绑定错误:Invalid bound statement (not found)
- OpenCV 张正友标定法的实现
- N皇后问题
- 【数据结构】【OI】二项堆的原理及代码实现
- asp.net创建helloWord
- HQL 多表联合查询
- JavaScript中forEach、for-in、for-of循环的比较
- 使用pyspark进行机器学习(回归问题)
- 1.break 2.continue 3. return
- AndFix实例讲解
- 设计模式C++实现(1)——工厂模式
- FFMPEG 流媒体协议