目录
2.4 第四种情况:删除非叶子结点,且该结点既有左子节点又有右子节点。
一、AVL树介绍-----平衡二叉搜索树
1.1 什么是二叉搜索树(BST树)?
二叉搜索树的两个特点:
- 根结点的值大于左子树上任意一个结点的值。
- 根结点的值小于右子树上任意一个结点的值。
1.2 AVL树的特点
- 拥有二叉搜索树的特点
- AVL树上任意两个子树的高度差最大为1。
- AVL树的 查找、插入、删除在平均和最差的情况下的时间复杂度都是O(logn)。
1.3 AVL树调整结构
1.3.1 平衡因子
平衡因子:某个结点的左子树高度减去右子树高度得到的差值。
AVL树:所有结点的平衡因子的绝对值不超过1的二叉树。
1.3.2 树的平衡化操作(左旋和右旋)
二叉树的平衡化操作一共有两个基础操作:左旋和右旋。这种操作在整个平衡化过程中可能执行一次或多次,这两种操作都是从 失去平衡的最小子树根结点开始的(即离插入结点最近且平衡因子超过1的祖结点)。
[左旋]
如下:假设插入结点为C,那么A结点的平衡因子是2,大于1,所以A结点就是不平衡点。
先把A结点和B结点进行"父子交换",即 B结点成了A的父节点,A成了B的子节点(左子树)。
更详细的如下动图:
S结点对应上图的B,如果S有左子树的话,那么在”父子交换后“,S的左子树就变成E(即上图的A)的右子树。
总结:
左旋过程就是:
不平衡结点(上图E结点) 与 它的右子结点S 进行”父子交换“(E会变成S的左子节点)。
那原本S的左子节点怎么办呢?很简单,变成E的右子节点。
[右旋]
如下:其实右旋跟左旋相似,只是方向变了而已。
总结:
右旋过程就是:
不平衡结点(上图的S结点) 与它的 左子节点E 做”父子交换“。 E变成S 的父节点,S变成E的新的右子节点。
那原本E的右子节点怎么办呢?那它就变成 S的左子节点。
1.3.3 AVL树四种失平衡情况之一 --- LL型
所谓的LL型就是上图,即因为在 最近不平衡结点(即n结点) 的左孩子的左子树添加了新节点,导致 n结点 的平衡因子变成了+2,二叉树失去了平衡。
解决方法:对失衡结点n右旋一次即可。
1.3.4 AVL树四种失去平衡情况之二 --- RR型
RR如上图,即因为在 最近不平衡结点y的右孩子的右子树添加了新节点,导致 y结点 的平衡因子变成了-2,二叉树失去了平衡。
解决方法:对失衡结点左旋一次即可。
1.3.5 AVL树四种失去平衡情况之三 --- LR型
LR型如上图,即有新的节点插入到 最近不平衡结点(即n结点) 的左孩子的右子树上,使得结点n的平衡因子变为2,二叉树失去平衡。
解决方法:先左旋 ,再右旋。
1.3.6 AVL树四种失去平衡情况之四 --- RL型
RL型如上图,即有新的结点插入到 最近不平衡结点(即10结点) 的右孩子的左子树上,使得 10结点 的平衡因子变成-2,二叉树失去平衡。
解决方法:先右旋, 再左旋。
总结:
LL:右旋
RR:左旋
LR:先左后右旋
RL:先右再左旋
二、AVL树删除结点的过程
2.1 第一种情况:删除叶子结点
操作:直接删除,然后依次向上调整(旋转)AVL树。
下面是几个例子:
直接删除结点1,发现二叉树没失衡,所以不需要调整。
直接删除结点9,发现二叉树没失衡,所以不需要调整。
删除结点4,删除结点4后,节点3就失衡了,然后进行一次右旋,就可以了。
删除结点6,删除结点6后,结点7失衡,然后进行一次左旋就可以了。
2.2 第二种情况:删除非叶子结点,且该结点只有左孩子
操作:用该结点的左孩子的值替换该结点的值,然后直接删除其左孩子结点。
2.3 第三种情况:删除非叶子结点,且该结点只有右孩子
操作:右孩子结点替换要被删除结点的值,然后删除右孩子结点。
2.4 第四种情况:删除非叶子结点,且该结点既有左子节点又有右子节点。
操作:这种情况,先找到要被删除的结点的前驱结点(或者后继结点也行),然后用前驱结点(或后继结点)的值替代被删除结点的值,然后就将前驱(或后继)节点删掉,怎么删除呢?其实删除的方式跟情况二、三是一样的。(注意,这种情况选择前驱结点也行,后继结点都行)
前驱结点和后继结点:数值上比当前结点少1的结点,如5的前驱结点就是4。后继结点就是6。
2.5 总结
添加和删除的时间复杂度都是O(logn)的原因是,要先查询到对应添加和删除结点的位置,而查询的时间复杂度就是O(logn)。
添加过程:由于是添加之前的AVL树是已经平衡的了,由于插入操作只会在树的叶子结点处进行插入,所以如果是由于插入使得不平衡,那只需要判断是LL\RR\LR\RL哪一种不平衡,而采取对应的旋转方式就可以了。所以调整次数为O(1)。
删除过程:由于删除过程删除的结点有可能是AVL树的任意一个结点, 因此会存在最坏的情况,就是会导致整棵树的结点都需要调整,那此时的最大调整次数就是O(logn)。因为旋转调整过程,是会改变局部树的结构的,局部的改变又会影响到更上层结点的平衡因子。但添加结点过程不会出现这种问题的原因是,添加结点只会在最底层添加。