平衡二叉排序树插入结点的学习总结

最近写了平衡二叉排序树代码,在这里对自己的理解做一下总结。


下面的文字,更多的是把我自己的遇到的理解上的问题和思路讲清楚,可能不能让你一下就看明白,这是我的问题。网上其实有很多写的很好的文章,我也是学他们的,然后通过写文章来考研自己是不是真的理解平衡二叉树,如果你在看完文章有任何疑惑,请留言。

下面几张图片是从这里拿过来的:http://blog.sina.com.cn/s/blog_616e189f0100qgcm.html,这位老师讲的很好。


首先描述一些基本的概念:

1.二叉排序树的特点:在一棵二叉排序树中,对任何一个结点来说,如果不为null,那么该结点就大于它左子树的全部结点,并小于它右子树的所有结点。


创建一棵二叉排序树,通常是给定一组序列,比如[23,12,5,2,29,9],来创建树。但是当给定的序列顺序不同的时候,所创建出来的树的形态就不一样,有的比较“平稳”,有的则显的很“陡峭”。然而对于不同的二叉树形态,其查询的平均时间消耗是有差异的。可以证明,当二叉排序树中任何一个结点的左子树的层数减去右子树的层数为1,-1,或0时,其平均查询时间是最少的。于是优化二叉排序树就引入了平衡的处理——平衡二叉排序树(下面称BSTree)。


2.BSTree中每个结点的BF值(平衡因子):指的是该结点的左子树的层数减去右子树的层数。


由于平衡二叉排序树在每插入一个结点时,都有义务保证插入结点后,整棵树还是符合平衡条件的,所以我们必须相信在你插入结点前,眼前的这棵树它就是平衡的。


我先用一种自上而下的思路来和大家一起感性的认识BSTree中插入结点的过程。因为是树的原因,所以在思考的时候一不小心就递归进去了,这问题变的很凌乱。所以在这部分内容的时候请大家放松,不用多想,只要你觉得下面分析的每一个步骤有道理就行了


《平衡二叉排序树插入结点的学习总结》

图说明:t结点的值不会和树中任何一个结点相等,也就是说它是可插入的,不然就没必要讨论了。


现在假如在你脑子里就有了一棵BSTree(具体什么样子随你想象,但必须符合平衡条件)。上图中的A结点并不一定就是最上面的根结点(Root),它可以代表一棵BSTree中任何一个结点,强调这一点是想使得问题得到归纳,不然容易失去方向。而A结点的BF值只有3种情况0,1,-1(反正不可能是2)。


旁边还有一个等待插入的结点t,,它可能比A大,也可能比A小,但是t到底插入A的左边还是插入右边都无所谓,其最后的操作都是一样的——这就是对称之美。所以我们只需要理解左边的情况,右边的也就迎刃而解,在一次强调!只需要理解“一半”!因为你的思维极有可能在看下面的文字的时候,时不时的会“跑偏”,这种“跑偏”是绝对浪费力气的,都说了是一样的。


我现在假设t将插入到A的左子树(下面称ALeftTree)当中。

那么ALeftTree的层数有且仅有2种变化:

1.层数不变  不会影响A结点的BF值

理解:A的右子树层数明显不变,现在ALeftTree的层数也不变,那么A的BF当然不变了。我还想多说一句,当在ALeftTree中插入一个结点后,它的层次没有变化,那么在ALeftTree中,必然有这么一个结点因为t的插入,它的BF变成了0。为什么呢?因为这是一个二叉树,呵呵。


2.层数 +1 这个时候你想想看,A的右子树的层数明显不变,而ALeftTree层数+1了,那么A的BF也必然要+1。之前说了,在插入t之前,A的BF有3中可能的情况,所以接下来分别讨论:

一) A:BF=0

A:BF=1

你看,当A的BF由0->1,以A结点为根的子树的层数是不是多了一层呢?这个时候我就又要去计算A的父结点的BF值了,其实这种情况和现在的ALeftTree一样。好了!Stop!不要在想下去了。

二) A:BF=-1

A:BF=0

A的BF=-1,表示A的“左腿”(左子树)比“右腿”(右子树)短,现在由于t的插入,使得A的2条腿一样长,那么A当然不会影响它父亲的BF了。所以当遇到这种情况,我就能肯定的说t结点的插入没有使树失衡,该结点插入完成。

三) A:BF=1

A:BF=2

这个时候该树就失衡了,而因为t结点最后的落点不同,在进行平衡处理的时候也产生了不同的方法。看过其他此类文章的同学知道我接下来要说那4种蛋疼的旋转了。又一次强调!现在只讨论t结点落入ALeftTree的情况,所以有“左左”和“左右”这2种情况(还有2种是“右右”和“右左”)。

左左的意思是:t结点落入了A结点的左孩子的左子树。

左右的意思是:t结点落入了A结点的左孩子的右子树。


《平衡二叉排序树插入结点的学习总结》

这是处理“左左”的旋转情况,这图我相信你能看懂,但是我想解释一下,我当时不懂的问题:在插入结点前,也就是左上角这棵树中,为什么A的左子树的根结点的BF值就是0呢?它不能是1或者-1吗?因为我觉得,L(B)的层数可能是h-1啊!

其实这个疑惑马上的就能被推翻,因为之前提到了一个前提,说由于t的插入,A的左子树多了一层。如果在插入前B的BF值就等于1或者-1,那么现在又多了一层,那B就变成2或-2了呀!(其实我还没有说明“最小不平衡子树”的概念。这个概念保证A是第一个不平衡结点,也就是BF=2或-2的结点)你如果还要继续想下去的话,恭喜你又掉进递归的洞洞里面去了,因为现在就在讨论A结点为2的情况。其他的理解应该没有问题。


那么新结点凭什么就插在B的左子树里面呢,不能插在了右边吗?可以啊,看下图。

《平衡二叉排序树插入结点的学习总结》

同样的,在这幅图里面,为什么左上角这棵,其c结点的BF也是0呢?我想说解释和前面的一样。那你可能为问:照你这么说,递归下去,那A的左子树简直就是一棵完全二叉树啊,这和我的想象不一样啊!

我想说,你先在这里mark一下,到后面提到的最小不平衡子树的概念时,在回来看,这些都不是问题!


其实看到这里,我希望你至少对“旋转”这个动作不反感了。至于图片里面有很多h之类的,先不用管,只要知道是怎么旋转的就行。


下面我在用一种自下而上的思路来理解t插入的过程,以及各结点的BF是怎样变化的过程。


《平衡二叉排序树插入结点的学习总结》

该图左边的树是平衡的,然后插入了39。当插入一个结点的时候,它只可能影响它所经过插入路径上的结点(如上图的黄色线段),其他的结点的BF是不变的。

我们看到,在这条路径上,可能有一个失衡点,也可能有多个,但是我们只要把从下往上以最小的失衡点为根的子树变成平衡,那么就能保证整棵树都变成平衡的,那么这是为什么呢?

我们以上图为例,设43为A结点。

先说清楚一点,对树中任何一个结点(左右子树不能为null),管它是不是平衡点,旋转后的效果就是一边减少一层,另一边加一层。

所以对于A这样的失衡结点,进行旋转后,该子树的层数和插入39之前的层数是一样的,所以整棵树都回到平衡了。


另外结点的BF怎么变,直接看文章开头的那个连接,已经讲的很清楚了。

    原文作者:平衡二叉树
    原文地址: https://blog.csdn.net/wxlfight/article/details/7818362
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞