- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
1的节点旋转到根-HIT(WH)ACMICPCCLUB
平衡树
HITACM 金卓林
二叉查找树,支持在二叉树上的查找操作,树中所有结点均满足以下条件。
1、若该结点有左子树,则该节点的左子树中所有结点的权值均小于该节点。
2、若该结点有右子树,则该节点的右子树中所有结点的权值均大于该节点。
3、该结点的左右子树也为二叉查找树。
BST
二叉搜索树是一颗满足如下性质的二叉树:左子树值=根节点值=右子树值。因此理论上我们可以在O(logN)的时间内完成插入、删除、查找等操作。是一种在“动态维护”中效果相当不错的数据结构。但由于题目数据的原因,可能造成二叉查找树并不平衡(严重的时候可能退化为线性),致使插入、删除、查找等操作的复杂度退化为O(N)。为了尽量保持二叉搜索树的平衡,我们需要去维护二叉搜索树——平衡二叉树。
Treap
我们建立二叉树的时候都想尽量建立趋近平衡的二叉树,但是由于数据的原因有时候并不能如意,treap的思路就是为每一个节点加一个元素 priority ,priority的值随机给出,用两种关键值进行建树以达到随机建树的目的。使建立的二叉树尽量平衡。
treap=tree+heap
主要有几大操作:插入,删除,查找,旋转,找第K大元素,找关键字x的排名,计算Treap的高度,删除
在树中维护一个优先级“,”优先级“
采用随机数的方法,但是”优先级“必须满足根堆的性质,当然是“大根堆”或者“小根堆”都无所谓,比如下面的一棵树:
左左情况旋转
右右情况旋转
删除
跟普通的二叉查找树一样,删除结点存在三种情况。
①:叶子结点
跟普通查找树一样,直接释放本节点即可。
②:单孩子结点
跟普通查找树一样操作。
③:满孩子结点
其实在treap中删除满孩子结点有两种方式。
第一种:跟普通的二叉查找树一样,找到“右子树”的最左结点(15),拷贝元素的值,但不拷贝元素的优先级,然后在右子树中删除“结点15”即可,最终效果如下图。
第二种:将”结点下旋“,直到该节点不是”满孩子的情况“,该赋null的赋null,该将孩子结点顶上的就顶上,如下图:
统计第k大的数
需要记录每个节点的左儿子数和右儿子数,如果这个k小于左儿子数,那么一定在左子树中,如果相等,就是这个节点,如果k大于左儿子数,那么一定在右子树中,也就是找第k-(P-lsize() + P-weight)个数,【p-weight存储的是这个数有多少个
例:poj 1442
求元素的排名
1.定义P为当前访问的节点,cur为当前已知的比要求的元素小的元素个数。从根节点开
始查找要求的元素,初始化cur为0;?2.?若要求的元素等于当前节点元素,要求的元素的排名为区间[P.left.size?+?cur?+?1,?P.left.size?
+?cur?+?weight]内任意整数;?
3.?若要求的元素小于当前节点元素,在左子树中查找要求的元素的排名;?
4.?若要求的元素大于当前节点元素,更新cur为cur?+?P.left.size+weight,在右子树中查找
要求的元素的排名
优先队列的实现
而我们可以方便地使用Treap实现双端优先队列,只需建立一个Treap,分别写出取最大值和最小值的功能代码就可以了,无需做任何修改。由于Treap平衡性不如堆完美,但期望时间仍是O(logN)。更重要的是在实现的复杂程度上大大下降,而且便于其他操作的推广。所以,用Treap实现优先队列不失为一种便捷而又灵活的方法。
Splay
一种对于BST的改进,能够保证均摊O(log2n)的复杂度。
优点:
1.相对于其他平衡树,Splay的空间需求小
2.Splay的编程复杂度低
Splay的实现
Splay本身是一颗BST,唯一的不同在于Splay具有自我调整的功能。
伸展操作 : Splay(x, root)
将结点x旋转到所在的子树的根节点root的位置上。
伸展操作Splay(x,S)
伸展操作Splay(x,S):是在保持Splay有序性的前提下,通过一系列旋转操作将Splay_S中的元素x调整至树的根部的操作。
在旋转的过程中,要分三种情况分别处理
1)Zig 或 Zag
2)Zig-Zig 或 Zag-Zag
3)Zig-Zag 或 Zag-Zig
旋转分为左旋和右旋,这两个是对称的。图示:
为了叙述的方便,上图的右旋叫做X绕Y右旋,左旋叫做Y绕X左旋。下图展示了将节点3旋转到根:
zig情况
X是查找路径上我们需要旋转的一个非根节点。
如果X的父节点是根,那么我们用下图所示的方法旋转X到根:
zig-zag情况。
在这种情况中,X有一个父节点P和祖父节点G(P的父节点)。X是右子节点,P是左子节点,或者反过来。这个就是双旋转。
先是X绕P左旋转
文档评论(0)