数据结构之 平衡二叉树

from https://www.cnblogs.com/zhujunxxxxx/p/3348798.htmlhtml

AVL树是根据它的发明者G.M. Adelson-Velsky和E.M. Landis命名的。它是最早发明的自平衡二叉查找树,也被称为高度平衡树。相比于"二叉查找树",它的特色是:AVL树中任何节点的两个子树的高度最大差异为1。它是一种高度平衡的二叉排序树。高度平衡?意思是说,要么它是一棵空树,要么它的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1。linux

    将二叉树上结点的左子树深度减去右子树深度的值称为平衡因子BF,那么平衡二叉树上的全部结点的平衡因子只多是-一、0和1。只要二叉树上有一个结点的平衡因子的绝对值大于1,则该二叉树就是不平衡的。 数组

    平衡二叉树的前提是它是一棵二叉排序树。 post

    距离插入结点最近的,且平衡因子的绝对值大于1的结点为根的子树,称为最小不平衡子树。以下图所示,当插入结点37时,距离它最近的平衡因子的绝对值超过1的结点是58。学习


 

一、平衡二叉树实现原理 spa

    平衡二叉树构建的基本思想就是在构建二叉排序树的过程当中,每当插入一个结点时,先检查是否因插入而破坏了树的平衡性,如果,则找出最小不平衡子树。在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的连接关系,进行相应的旋转,使之成为新的平衡子树。 下面讲解一个平衡二叉树构建过程的例子。如今又a[10] = {3, 2, 1, 4, 5, 6, 7, 10, 9, 8}须要构建二叉排序树。在没有学习平衡二叉树以前,根据二叉排序树的特性,一般会将它构建成以下左图。虽然彻底符合二叉排序树的定义,可是对这样高度达到8的二叉树来讲,查找是很是不利的。所以,更加指望构建出以下右图的样子,高度为4的二叉排序树,这样才能够提供高效的查找效率。3d

 

    如今来看看如何将一个数组构成出如上右图的树结构。 对于数组a的前两位3和2,很正常地构建,到了第个数“1”时,发现此时根结点“3”的平衡因子变成了2,此时整棵树都成了最小不平衡子树,须要进行调整,以下图图1(结点左上角数字为平衡因子BF值)。由于BF为正,所以将整个树进行右旋(顺时针),此时结点2成了根结点,3成了2的右孩子,这样三个结点的BF值均为0,很是的平衡,以下图图2所示。htm

    而后再增长结点4,平衡因子没有改变,如上图图3。增长结点5时,结点3的BF值为-2,说明要旋转了。因为BF是负值,对这棵最小平衡子树进行左旋(逆时针旋转),以下图图4,此时整个树又达到了平衡。blog

 

    继续增长结点6时,发现根结点2的BF值变成了-2,以下图图6所示。因此对根结点进行了左旋,注意此时原本结点3是结点3的左孩子,因为旋转后须要知足二叉排序树特性,所以它成告终点2的右孩子,如图7所示。排序

 

    增长结点7,一样的左旋转,使得整棵树达到平衡,以下图8和9所示。

    

    当增长结点10时,结构无变化,如图10所示。再增长结点9,此时结点7的BF变成了-2,理论上只须要旋转最小不平衡树七、九、10便可,可是,若是左旋转后,结点9变成了10的右孩子,这是不符合二叉排序树的特性的,此时不能简单的左旋。如图11所示。

    仔细观察图11,发现根本缘由在于结点7的BF是-2,而结点10的BF是1,也就是说,它们两个一正一负,符号并不统一,而前面的几回旋转,不管左仍是右旋,最小不平衡子树的根结点与它的子结点符号都是相同的。这就是不能直接旋转的关键。 不统一,不统一就把它们先转到符号统一再说,因而先对结点9和结点10进行右旋,使得结点10成了9的右子树,结点9的BF为-1,此时就与结点7的BF值符号统一了,如图12所示。

     

    这样再以结点7为最小不平衡子树进行左旋,获得以下图13。接着,插入8,状况与刚才相似,结点6的BF是-2,而它的右孩子9的BF是1,如图14,所以首先以9为根结点,进行右旋,获得图15,此时结点6和结点7的符号都是负,再以6为根结点左旋,最终获得最后的平衡二叉树,如图16所示。

  

    经过这个例子,能够发现,当最小不平衡树根结点的平衡因子BF是大于1时,就右旋,小于-1时就左旋,如上例中的结点一、五、六、7的插入等。插入结点后,最小不平衡子树的BF与它的子树的BF符号相反时,就须要对结点先进行一次旋转以使得符号相同后,再反向旋转一次才可以完成平衡操做,如上例中结点九、8的插入时。

    目前linux kernel里已再也不使用平衡二叉树,代之以红黑树rbtree。

相关文章
相关标签/搜索