1. 什么是AVL树
1.1. 简介
AVL树又称为高度平衡的二叉搜索树,目的在于尽量降低二叉树的高度,减少平均搜索长度。
1.2. AVL树的性质
- 左子树和右子树高度差的绝对值不超过1
- 树中的每一个左子树和右子树都是AVL树
- 每一个节点都有一个平衡因子,AVL树中任意节点的平衡因子可取值为-1,1,0
(平衡因子就是 右子树的高度-左子树的高度)
2. 插入、删除、查找效率
一棵AVL树有N个节点,高度可以保持在log2N
插入、删除、查找的时间复杂度是O(log2N)
3. 平衡因子更新规则
- 左子树插入节点,该节点的父节点bf -= 1
- 右子树插入节点,该节点的父节点bf += 1
4. AVL树的插入
当插入一个节点后当前节点的父节点的平衡因子变为0,说明当前树是平衡的,不会对上层节点产生影响,所以结束更新直接返回。
假如插入节点之后该节点的父节点平衡因子变为1或者-1,此时说明之前父节点的平衡因子是0,那就破坏了平衡,那就会对上层节点的平衡性产生影响。此时就需要不断循环向上层更新,只要上层是1或者-1,循环就无法停下,直到父节点为根节点为止,才算插入完毕。
(循环向上层更新父节点出现的)如果父节点的平衡因子变成-2 或者2,那么就要进行旋转,更新节点的bf值,调整树的高度。
节点的平衡因子为-3 或者3,这种情况是不可能出现的,如果有说明原来的树就不是AVL树。我们要保证每个树再插入之前都是一颗AVL树。
5. 判断一棵树是否为AVL树
5.1. 递归判断
class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null){
return true;
}
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return (Math.abs(left-right)<2)&&isBalanced(root.left)&&isBalanced(root.right);
}
public static int maxDepth(TreeNode root){
if(root == null){
return 0;
}
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return (left>right?left:right)+1;
}
}
5.2. 迭代判断
class Solution {
public boolean isBalanced(TreeNode root) {
return function(root).balance;
}
public IsBalance function(TreeNode root){
IsBalance res = new IsBalance();
res.height = 0;
res.balance = true;
if(root == null){
return res;
}
IsBalance lres = new IsBalance();
lres = function(root.left);
if(lres.balance==false){
return lres;
}
IsBalance rres = new IsBalance();
rres = function(root.right);
if(rres.balance==false){
return rres;
}
res.height = (lres.height>rres.height)?lres.height+1:rres.height+1;
res.balance = Math.abs(lres.height-rres.height)<2;
return res;
}
class IsBalance{
public int height;
public boolean balance;
}
}