- 面试官老是问红黑树,但我又比较懒,不想学,学了又忘,但是以前参加acm比赛的时候写过其他的平衡二叉树,所以就和面试官吹了下。
Splay
- splay即伸展树,与其他树不同的是它具有伸展操作,伸展操作Splay(x,S)是在保持伸展树有序性的前提下,通过一系列旋转将伸展树S中的元素x调整至树的根部。
- 为了使整个查找时间更少,被查频率高的那些结点应当经常处于靠近树根的位置。Splay树可以通过旋转的方式把被访问结点旋转到树根的位置以减少查找时间,不需要存储平衡信息,简而言之,就是我插入或者查询的节点我使用的频率比较高,那我就把这些节点旋转到根。
AVL树
- avl树是维护平衡因子小于1来保持树的平衡,平衡因子即左右子树高度之差,等于右子树高度-左子树高度的绝对值,如果平衡因子超过1, 则需要一直旋转保持树的绝对平衡,可能会导致旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。因此如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的,可以考虑AVL树,但一个结构经常修改,就不太适合。
SBT树
- SBT树即节点平衡树,其实是英文Size balanced tree的缩写,每个节点都有一个size值,对于树上某个节点而言,它的size指的是以它为树根的子树当中节点的数量。
- SBT树需要满足每棵子树的大小不小于其兄弟的子树大小,即s[right[t]]≥s[left[left[t]]],s[right[left[t]]] 且 s[left[t]]≥s[right[right[t]]], s[left[right[t]]],如果插入结点后不满足SBT性质,那么递归修复这棵树的性质。
- 通过旋转达到目的。SBT改进了AVL的平衡条件,不再是严格限制左右子的高度差<=1了。
treap树
- Treap一词是Tree和Heap的合成词,也就是这是一棵带有堆性质的树,即树堆,trap树还维护了一个优先级rank值,把每个节点的优先级进行随机赋值,那么生成的Treap树形态也是随机的。这虽然不能保证每次生成的Treap树一定时平衡的,但是期望的插入、删除、查找的复杂度都是O(logn)的。总的说来,对于键值来说,Treap是一棵排序二叉树,对于优先级来说,Treap是一个堆,根节点的优先级是最高的。如果不满足堆的特性,则旋转来满足。
总结
- 实现二叉树平衡的方法有很多,同样定义一棵二叉树是否平衡的标准也有很多,这里也只是简单介绍了除红黑树之外的平衡二叉树,简要对比了各种二叉树的平衡策略,至于旋转都大同小异,所谓的平衡策略是采取什么样的方式来做到二叉树的平衡,红黑树是通过将节点区分为红色和黑色,满足5个特性来满足平衡,伸展树是以概率的角度来达到平衡,avl树是通过满足高度差,sbt树是通过统计节点的size,treap则额外维护了一个堆来满足平衡。