AVL树(java实现)

一、AVL树的四种旋转操作
(1)右旋
这里写图片描述
代码:

/**
     * 右旋
     *
     * @param root
     * @return
     */

    private AvlNode rigthRotate(AvlNode root) {
        AvlNode newroot = root.left;
        root.left = newroot.right;
        newroot.left = root;
        root.height = Math.max(height(root.left), height(root.right)) + 1;
        newroot.height = Math.max(height(newroot.left), height(newroot.right)) + 1;
        return newroot;
    }

(2)左旋
这里写图片描述
代码:

 /**
     * AVL树的左旋转操作,从root开始,进行左旋,完成后,把新的根节点返回
     *
     * @param root
     * @return
     */
    private AvlNode leftRotate(AvlNode root) {
        AvlNode newroot = root.right;
        root.right = newroot.left;
        newroot.left = root;
        root.height = Math.max(height(root.left), height(root.right)) + 1;
        newroot.height = Math.max(height(newroot.left), height(newroot.right)) + 1;
        return newroot;

    }

(3) 左右旋
这里写图片描述
代码:

 /**
     * 左右旋转
     *
     * @param root
     * @return
     */
    private AvlNode leftBalance(AvlNode root) {
        root.left = leftRotate(root.left);
        return rigthRotate(root);
    }

(4)右左旋
这里写图片描述
代码:

 /**
     * 右左旋转
     */
    private AvlNode rightBalance(AvlNode root) {
        root.right = rigthRotate(root.right);
        return leftRotate(root);
    }

二、AVL树的插入和删除
(1)插入

/**
     * 插入操作
     *
     * @param val
     * @return
     */
    public void insert(int val) {
        root = insert(root, val);
    }

    private AvlNode insert(AvlNode root, int val) {
        if (root == null) {
            return new AvlNode(val, null, null, 1);
        }
        if (val > root.data) {
            root.right = insert(root.right, val);
            if (height(root.right) - height(root.left) > 1) {
                if (val > root.right.data) {      //插入到右孩子的右子树  进行LL旋转
                    root = leftRotate(root);
                } else {
                    root = rightBalance(root);       //插入到右子树的左子树  进行RL旋转
                }
            }
        } else if (val < root.data) {
            root.left = insert(root.left, val);
            if (height(root.left) - height(root.right) > 1) {
                if (val < root.left.data) {          //插入到左孩子的左子树   进行RR
                    root = rigthRotate(root);
                } else {
                    root = leftBalance(root);    //插入到左孩子的右子树  进行RL旋转
                }
            }
        } else {
            System.out.println("不能插入相同的结点");
        }
        //由于插入了新的结点 ,需要更新树的高度;
        root.height = Math.max(height(root.left), height(root.right)) + 1;
        return root;
    }

(2)删除操作

 /**
     * 删除结点
     */
    public void remove(int val) {
        remove(root, val);
    }

    private AvlNode remove(AvlNode root, int val) {
        if (root == null) {
            return null;
        }
        if (val > root.data) {
            root.right = remove(root.right, val);
            if (height(root.left) - height(root.right) > 1) {
                //判断要删除的结点在左孩子的那个子树上  此时结点已删除  只能从左子树高度来判断
                if (height(root.left.left) >= height(root.left.right)) {  //左孩子的右子树高
                    root = rigthRotate(root);
                } else {       //左孩子的左子树高
                    root = leftBalance(root);
                }
            }
        } else if (val < root.data) {
            root.left = remove(root.left, val);
            if (height(root.right) - height(root.left) > 1) {
                //判断要删除的结点在右孩子的那个子树上
                if (height(root.right.left) > height(root.right.right)) {  //右孩子的左子树高
                    root = rightBalance(root);
                } else {             //右孩子的右子树高
                    root = leftRotate(root);
                }
            }
        } else {
            if (root.left != null && root.right != null) {
                //判断root的左子树高,用前驱(左孩子的右子树)代替
                if (height(root.left) > height(root.right)) {
                    AvlNode tmp = root.left;
                    while (tmp.right != null) {
                        tmp = tmp.right;
                    }
                    root.data = tmp.data;
                    root.left = remove(root.left, tmp.data);
                } else {   //右子树高 用后继(右孩子的左子树)代替
                    AvlNode tmp = root.right;
                    while (tmp.left != null) {
                        tmp = tmp.left;
                    }
                    root.data = tmp.data;
                    root.right = remove(root.right, tmp.data);
                }
            } else {
                if (root.right != null) {
                    return root.right;
                }
                if (root.left != null) {
                    return root.left;
                }
                return null;
            }
        }
        root.height = Math.max(height(root.left), height(root.right)) + 1;
        return root;
    }

猜你喜欢

转载自blog.csdn.net/xd_fybdw/article/details/81036484