AVL Tree 平衡二叉树 Java实现

先介绍一个概念:

Height balance property: For every internal node v of T, the height of the children of v differs by 1 at most. 每个子结点的高度差最多为1.

符合Height balance property的BST叫做AVL Tree,平衡二叉树。

对于一个有n个节点的平衡二叉树来说,它的高度是O(logn),证明参考:点击打开链接

AVL的插入操作与BST的插入操作相似,之后还要再进行一步判断Tree 是否达到平衡。这里引入函数getBalance返回左右子节点的高度差。设Z是我们判断的对象,y是z在插入路径上的子节点,x是插入路径上的孙子节点。判断的结果通常为以下4种:

  1. left left case : we need to right rotate the tree for once
  2. left right case: First, we need to right rotate the tree, then to left rotate the tree
  3. right right case : we need to left rotate the tree for once
  4. right left case: First, we need to left rotate the tree, then to right rotate the tree



insert()方法

    public int height(Node node){
        if (node == null) return 0;
        return node.height;

    }

    public Node leftRotate(Node node){
        Node y = node.right;
        Node T2 = y.left;

        y.left = node;
        node.right = T2;

        node.height = Math.max(height(node.left),height(node.right));
        y.height = Math.max(height(y.left), height(y.right));

        return y;
    }

    public Node rightRotate(Node node){
        Node x = node.left;
        Node T1 = x.right;

        x.right = node;
        node.left = T1;

        node.height = Math.max(height(node.left),height(node.right));
        x.height = Math.max(height(x.left), height(x.right));
        return x;
    }

    public int getBalance(Node node){
        if (node == null){
            return 0;
        }
        return height(node.left) - height(node.right);
    }

    public Node insert(Node node, int key){
        if (node == null){
            return (new Node(key));

        }
        if (key < node.key){
            node.left = insert(node.left,key);
        } else if (key > node.key){
            node.right = insert(node.right,key);
        } else {
            return node;
        }

        node.height = 1 + Math.max(height(node.left), height(node.right));

        int balance = getBalance(node);
        // Left Left case
        if (balance > 1 && key < node.left.key){
            return rightRotate(node);
        }
        // Right Right case
        if (balance < -1 && key > node.right.key){
            return leftRotate(node);
        }
        // Left right case
        if (balance > 1 && key > node.left.key){
            node.left = leftRotate(node.left);
            return rightRotate(node);
        }
        // Right left case
        if (balance < -1 && key < node.right.key){
            node.right = rightRotate(node.right);
            return leftRotate(node);
        }
        return node;
    }

delete()方法,与BST中的delete相似,在执行了delete操作之后需要检查tree是否达到balanced状态,引入平衡因子balance和getBalance()方法。在AVL Tree中的insert和delete都用到了递归,可以画stack图来加深对递归的理解。比如insert中,每执行一次递归,都会增加一个stack frame用于执行insert方法,一直到node == null,返回新建的node。stack frame从上往下逐层消失,返回值一层一层往下递送。

    public Node deleteNode(Node root, int key){
        if (root == null){
            return root;
        }
        if (key < root.key){
            root.left = deleteNode(root.left,key);
        } else if (key > root.key){
            root.right = deleteNode(root.right,key);
        } else {
            if (root.left == null || root.right == null){
                Node temp = null;
                if (root.left == temp){
                    temp = root.right;
                } else {
                    temp =root.left;
                }
                if (temp == null){
                    temp = root;
                    root = null;
                }
            }
            else {
                //node with two children
                Node temp = getReplacement(root.right);
                root.key = temp.key;
                root.right = deleteNode(root.right,temp.key);
            }
        }
        if (root == null){
            return root;
        }
        root.height = Math.max(height(root.left),height(root.right));
        int balance = getBalance(root);
        if (balance > 1 && getBalance(root.left) >= 0){
            return rightRotate(root);
        }
        if (balance > 1 && getBalance(root.left) < 0){
            root.left = leftRotate(root.left);
            return rightRotate(root);
        }
        if (balance < -1 && getBalance(root.right) <= 0){
            return leftRotate(root);
        }
        if (balance < -1 && getBalance(root.right) > 0){
            root.right = rightRotate(root.right);
            return leftRotate(root);
        }
        return root;
    }


猜你喜欢

转载自blog.csdn.net/everest115/article/details/79601586