AVL树右旋转思路分析与图解
其实我们前面讲过了左旋转之后再学习右旋转就会非常的简单了, 因为我们的右旋转相对我们的左旋转只是换了一个方向而已, 那么下面我们就来讲解右旋转的实现
对于数列{10, 12, 8, 9 ,7, 6} , 当我们插入6的时候leftHeight() - rightHeight() > 1成立(也就是此时的树成为了一颗不平衡树, 并且这个时候我们观察构成的AVL树之后我们可以发现此时的最小不平衡子树是一个LL型的不平衡子树), 所以这个时候我们就要采用某种操作让这个不平衡的树重新平衡起来, 那么我们要如何处理之后可以让这个树重新平衡起来?
那么如何实现右旋转? 我们这里通过图解来进行描述:
右旋转的具体实现过程:
- 创建一个新的结点newNode, 值等于当前最小不平衡二叉树根节点的值
- 让新结点newNode的右子结点指向当前根节点的右子树
- 让新结点的左子节点指向当前根节点的左子节点的右子树
- 让当前根节点的值换为当前根节点的左子节点的值
- 因为右旋的时候旧根节点的左子结点的值就是我们的新根节点值
- 把根节点的左子树设置为当前根节点的左子树的左子树( 将原本存储新根节点值的结点从树中删除掉)
- 把根节点的右子树设置为新结点
注意: 整个过程中根节点是没有变的, 只是根节点的值发生了改变
右旋的核心思想: (两步)
- 原本旧根结点为现在新根节点的右子树
- 原本新根节点的右子树变为现在旧根结点的左子树
这里我们来对左旋和右旋进行一个易错归纳(我们以左旋为例):
- 对于如下结构的左旋到底是如何实现的:
- 首先我们要知道上图的最小不平衡子树并不是整棵树, 而是如下的子树:
-
所以我们最终应该是对这个最小不平衡子树的根节点执行一个左旋的操作, 因为此时的最小不平衡子树显然是一个RR型最小不平衡子树, 最终这个最小不平衡子树会变成如下:
-
这个时候我们要注意: 我们的根节点一直没有变化过, 这个时候只是原本的根节点的值从3变为了4, 但是节点并没有发生变化, 所以也就是这个最小不平衡子树一直没有和整个树断开连接, 因为根节点始终没有变过, 所以最终平衡之后就会是如下:
-
最终得到了如上的平衡二叉树, 我们的平衡化就算是完成了, 但是这个时候有的人会提出一个思路: 就是我们可不可以通过改变指针的指向, 不用创建新的结点来完成这次左旋操作?(比如说改变②结点的指向, 直接让②结点指向④结点)
- 答案是不建议的(我们一般不这么做), 因为最终左旋操作是在递归中执行的, 最终我们是会拿到最小生成树的根节点, 也就是④结点, 所以我们无法改变②结点的指向, 如果我们非要拿到②结点肯定也是可以的, 但是这样的算法的效率可能就不会太高 —> 所以我们建议的就是通过建立一个新的节点的方式来完成, 这样的效率是比较高的, 并且实现起来的思路也比较简单