10、平衡二叉搜索树BBST
平衡二叉搜索树(Balanced Binary Search Tree BBST)是一种自平衡的二叉搜索树。所以自平衡意味着会自行调整,以保持较低(对数)的高度,从而允许更快的操作,例如插入和删除。
10.1、树旋转
大多数BBST算法核心组成部分是:树不变式
和树旋转
的巧妙用法。
树不变式:是在每次操作后必须满足的属性/规则。为了确保始终满足不变式,通常会应用一系列树旋转。
在树旋转的过程中需要确保保持BST的不变式:左子树比较小,右子树比较大。
10.1.1、更新单向指针的BBST
为此,我们可以使用以下操作实现右旋转,注意观察宣传前后,BST的不变式:
1 | public void rightRotate(Node a) { |
如下图,我们准备执行rightRotate(a)
:
为什么可以这样变换呢?
还是那个原则:BST不变式。
所有BBST都是BST,因此对于每个节点n,都有:n.left <n && n < n.right
。(这里的前提是没有重复元素)
我们在变换操作的时候只要确保这个条件成立即可,即保持BST不变性成立的前提下,我们可以对树中的值和节点进行随机变换/旋转。
注意,如上图,如果a节点还有父节点p,那么就把p节点原来指向a节点变更为指向b节点。
10.1.2、更新双向指针的BBST
在某些需要经常方位父节点或者同级节点的BBST中,我们就不是像上面那样最多更新3个指针,而是必须更新6个指针了,操作会复制些许。
以下是代码实现:
1 | public void rightRotate(Node a) { |
BBST通过在不满足其不变性时执行一系列左/右树旋转来保持平衡。
10.2、AVL树
AVL树是平衡二叉搜索树的一种,它允许以O(log(n))的复杂度进行插入、搜索和删除操作。
AVL树是第一种被发现的BBST,后来出现了其他类型包括: 2-3 tree、AA tree、scapegoat tree(替罪羊树)、red-black tree(红黑树)。
使AVL树保持平衡的属性称为平衡因子(balanced factor BF)。
BF(node) = H(node.right) - H(node.left)
其中H(x)是节点的高度,为x和最远的叶子之间的边数
AVL树中使其保持平衡的不变形是要求平衡因子BF始终为-1、0或者1。
10.2.1、节点存储信息
-
节点存储的实际值,此值必须可以比较;
-
BF的值;
-
节点在树中的高度;
-
指向左右子节点的指针。
10.2.2、AVL的自平衡
当节点的BF不为-1、0或者1的时候,使用树旋转来进行调整。可以分为几种情况:
左左
左右
右右
右左
10.3、从BBST中移除元素
参考BST小节的删除逻辑,与之不同的是,在删除元素之后,需要执行多一个自平衡的过程。
10.4、时间复杂度
普通二叉搜索树:
操作 | 平均复杂度 | 最差复杂度 |
---|---|---|
Insert | O(log(n)) | O(n) |
Delete | O(log(n)) | O(n) |
Remove | O(log(n)) | O(n) |
Search | O(log(n)) | O(n) |
平衡二叉搜索树:
操作 | 平均复杂度 | 最差复杂度 |
---|---|---|
Insert | O(log(n)) | O(log(n)) |
Delete | O(log(n)) | O(log(n)) |
Remove | O(log(n)) | O(log(n)) |
Search | O(log(n)) | O(log(n)) |
10.5、编程实践
References
Data Structures Easy to Advanced Course - Full Tutorial from a Google Engineer