一. 平衡树和AVL
常规二分搜索树的局限性:
- 常规的二分搜索树,有一个很大的局限性,即当数据是顺序输入时,此时的二分搜索树将退化成链表,性能上会有很大的降低
平衡二叉树:
- 对于任意一个节点,左子树和右子树的高度差不能超过1
- 平衡二叉树的高度和节点数量之间的关系也是O(logn)的
- 平衡二叉树需要标注每个节点的高度,节点的高度值为其左右子节点中的较大的高度值加一
- 平衡二叉树要计算平衡因子,即节点左右子树的高度差 (定义为:左子节点高度值 - 右子节点高度值) ,平衡二叉树要保证所有节点的平衡因子的绝对值都小于2
- 满二叉树和完全二叉树,是更为严格的平衡二叉树
二. AVL自平衡的实现
1.维护平衡的时机
在一棵平衡树的平衡性遭到破坏时,需要维护其平衡性,那么,原本一棵平衡的树在什么时候会发生平衡破坏呢?即在添加新的节点或者删除一个节点时时!且遭到平衡性破坏的节点一定是新添加节点或者删除节点的父辈节点,故,我们需要沿着新添加的叶子节点或者删除的节点一路向上维护整棵树的平衡性(add() 和 remove() 的递归过程中完成)。
2.自平衡的实现机制
情况一(LL):插入(或者删除)节点在最终不平衡节点的左侧的左侧,即 balanceFactor(node)>1 && balanceFactor(node.left)>=0 时,需要做右旋转。
情况二(RR):插入(或者删除)节点在最终不平衡节点的右侧的右侧,即 balanceFactor(node)< -1 && balanceFactor(node.right)<=0 时,需要做左旋转。
情况三(LR):插入(或者删除)节点在最终不平衡节点的左侧的右侧, 即 balanceFactor(node)>1 && balanceFactor(node.left)<0 时. 需要两步操作完成自平衡:
- 对x进行左旋转,此时变成LL的情况;
- 再对y进行右旋转,完成最终的自平衡;
情况四(RL):插入(或者删除)节点在最终不平衡节点的右侧的左侧, 即 balanceFactor(node)< -1 && balanceFactor(node.right)>0 时. 需要两步操作完成自平衡:
- 对x进行右旋转,此时变成RR的情况;
- 再对y进行左旋转,完成最终的自平衡;
三. AVL的扩展
- 底层基于AVL的Set与Map的实现
- AVL的优化:添加或者删除节点后,重新计算的节点高度值若没有改变,则可以省去自平衡过程;
- AVL的局限性:相对于红黑树,红黑树的平均性能更优(两者均是O(logn)级别的)