二叉平衡树
上一篇博客写到了二叉排序树,二叉排序树在最好的情况下,其时间复杂度为O(logn),而在最坏的情况下,二叉排序树变成一个线性表,查找也就变成了顺序查找,时间复杂度为O(n),所以二叉排序树的查找效率取决于树的形状,而树的形状又取决于构造树节点的元素序列,如果这个序列是完全有序的,那边构造出来的二叉排序树就是一个线性表了。如果能把二叉排序树整理得深度尽量小,那么查找的效率也就会比较高,其实二叉排序树在查找中比较的次数就是二叉树的层数。要想层数尽可能小,就需要树比较平衡。树中平衡概念是指根节点的左右子树的高度之差的绝对值不大于1,并且左右子树都是平衡的。有这种特性的树叫二叉平衡树,也叫AVL树。构造二叉平衡树用来查找,查找的速度会更快,查找的时间复杂度为O(logn)。
对于二叉排序树,由于添加删除节点可能会改变树的结构,所以添加删除节点做相应的处理来维持树的平衡。当添加节点时,每经过一个节点,就把这个节点入栈,这里用栈的好处是插入后要进行回溯来检查平衡是否被破坏。像二叉平衡树一样(
参照二叉排序树)找到要插入的位置,插入成功后进行回溯,检查所经过的节点的平衡因子,这个平衡因子是指以这个节点为根的树的所有叶子节点深度之差的最大值,如果树是平衡的,那么树中的每个节点的平衡因子的绝对值都小于等于1。在回溯的过程中,如果发现有哪个节点的平衡因子的绝对值大于1,就说明树的平衡被破坏了。当平衡被破坏后,就要进行相应的旋转处理来恢复平衡。
恢复平衡的旋转有单左旋和单右旋。
图中是单左旋。
单左旋的过程是,当B的右子树上添加了新节点,这时A节点的平衡因子为-2,失去平衡,通过左单旋,把B的左子树BL设置成A的右子树,再把A设置成B的左孩子,把B变成树的根节点。由于B为根的树的所有节点的元素都大于A,所以把BL变成A的右子树不会破坏二叉排序树的特性。A是小于B的,所以A可以成为B的左子节点,所以这种旋转不破坏二叉排序树的特性。由于这样变换了,BR上添加的节点所导致的不平衡被解决了,BR上添加的节点增加的深度被A来低效掉了。
这个过程可以简单地理解为为B为支点,把A向左下拉,然后把BL和B的连边断开,把BL连到A的右子节点上去,B就到了最上方,成为了根节点。
这个图中显示的是单右旋
当在BL子树中添加了节点后,A的平衡因子为2,以A为根的树失去平衡。单右旋时,把BR变成A的左子树,再把A变成B的右子树。和上同理,这样不会破坏二叉排序树的特性,并且A抵消了由于在BL中添加节点增加的深度。
这个过程也可以简单地理解成以B为支点,