平衡二叉搜索树---java---黑马

平衡二叉搜索树

AVL树的实现

  • 二叉搜索树在插入和删除时,节点可能发生失衡;
  • 如果在插入和删除时通过旋转,始终让二叉搜索树保持平衡,称之为平衡二叉搜索树
  • AVL树是自平衡二叉搜索树的实现之一

LL

- 失衡节点(图中5红色)的`bf>1`,即左边更高
- 失衡节点的左孩子(图中3 黄色)的`bf>=0`,即左孩子这边也是左边更高或等高

在这里插入图片描述

LR

- 失衡节点(图中6)的`bf>1`,即左边更高
- 失衡节点的左孩子(图中2 黄色)的`bf<0`,即左孩子这边是右边更高

在这里插入图片描述

RL

-失衡节点(图中2)的`bf<-1`,即右边更高
-失衡节点的右孩子(图中6黄色)的`bf>0`,即右孩子这边是左边更高

在这里插入图片描述

RR

-失衡节点(图中2红色)的`bf<-1`,即右边更高
-失衡节点的右孩子(图中6黄色)的`bf<=0`,即右孩子这边是右边更高或者等高

在这里插入图片描述

public class AVLTree{
    
    static class AVLNode{
        int key;
        Object value;
        AVLNode left;
        AVLNode right;
        int height = 1;
        
        public AVLNode (int key, Object value) {
            this.key = key;
            this.value = value;
        }
        
        public AVLNode (int key) {
            this.key = key;
        }
        
        public AVLNode (int key, Object value, AVLNode left, AVLNode right) {
            this.key = key;
            this.value = value;
            this.left = left;
            this.right = right;
        }
    }
    
    // 求节点高度
    public int height(AVLNode node) {
        return node == 0 ? 0 : node.height;
    }
    
    // 更新节点高度(新增、删除、旋转)
    public void updateHeight(AVLNode node) {
        node.height = Math.max(height(node.left), height(node.right)) + 1;
    }
    
    // 平衡因子(balance factor) = 左子树高度-右子树高度
    // bf = 0, -1, 1, 表示左右平衡
    // bf > 1, 表示左子树高
    // bf < -1, 表示右子树高
    public int bf(TreeNode node) {
        return height(node.left) - height(node.right);
    }
    
    // 输入要旋转的节点,返回新节点----右旋
    private AVLNode rightRotate(AVLNode red) {
        AVLNode yellow = red.left;
        AVLNode green = yellow.right;
        yellow.right = red;
        red.left = green;
        updateHeight(red);
        updateHeight(yellow);
        return yellow;
    }
    
    // 输入要旋转的节点,返回新节点----左旋
    private AVLNode leftRotate(AVLNode red) {
        AVLNode yellow = red.right;
        AVLNode green = yellow.left;
        yellow.left = red;
        red.righ = green;
        updateHeight(red);
        updateHeight(yellow);
        return yellow;
    }
    
    // 先左旋,后右旋----先左旋左子树,后右旋根节点
    private AVLNode leftRightRotate(AVLNode node) {
        node.left = leftRotate(node.left);
        return rightRotate(node);
    }
    
    // 先右旋右子树,后左旋根节点
    private AVLNode rightLeftRotate(AVLNode node) {
        node.right = rightRotate(node.right);
        return leftRotate(node);
    }
    
    // 检查是否平衡
    private AVLNode balance(AVLNode node) {
        if (node == null) {
            return node;
        }
        int bf = bf(node);
        if (bf > 1 && bf(node.left) >= 0) {		//LL
            rightRotate(node);
        } else if (bf > 1 && bf(node.left) < 0) {	// LR
            leftRightRotate(node);
        } else if (bf < -1 && bf(node.right) > 0) {		// RL
            rightLeftRotate(node);
        } else if (bf < -1 && bf(node.right) <= 0) {	// RR	
            leftRotate(node);
        }
    }
    
    AVLNode root;
    
    public void put(int key, Object value) {
        return doPut(root, key, value);
    } 
    
    private ALVNode doPut(AVLNode node, int key, Object value) {
        // 1.找到空位,创建新节点
        if (node == null) {
            return new AVLNode(key, value);
        }
        // 2.树中存在节点,做更新操作
        if (node.key == key) {
            node.value = value;
            return node;
        }
        // 3.查找操作
        if (key < node.key) {
            node.left = doPut(node.left, key, value);
        }
        if (key > node.key) {
            node.right = doPut(node.right, key, value);
        }
        // 更新高度,检查是否平衡
        updateHeight(node);
        return balance(node);
    }
    
    public void remove(int key) {
        root = doRemove(root, key);
    }
    
    public AVLNode doRemove(AVLNode node, int key) {
        // 1.节点为空
        if (node == null) {
            return null;
        }
        // 2.寻找节点
        if (key < node.key) {
            node.left = doRemove(node.left, key);
        } else if (key > node.key) {
            node.right = doRemove(node.right, key);
        } else {
            // 3.找到节点,判断删除节点是否有孩子
            if (node.left == null && node.right == null) {
                return null;
            } else if(node.left == null) {
                node = node.right;
            } else if (node.right == null) {
                node = node.left;
            } else {		// 左右子树均在
                // 在待删除节点的右子树zhon寻找待删除节点的后继节点
               	AVLNode s = node.right;
                while (s.left != null) {
                    s = s.left;
                }
                // 找到后继节点
                s.right = doRemove(node.right, s.key);
                s.left = node.left;
                node = s;
            }
        }
        updateHeight(node);
        return balance(node);
    }
}

删除操作

Remove(node.right, s.key);
s.left = node.left;
node = s;
}
}
updateHeight(node);
return balance(node);
}
}


删除操作
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/c65de9476563476ebd30192166eb8b07.png#pic_center)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值