Balanced Binary Tree—AVL Tree

In computer science, the AVL tree is the first self-balancing binary search tree invented. The maximum difference between the heights of the two subtrees of any node in the AVL tree is 1, so it is also called a height-balanced tree. Adding and deleting may require one or more tree rotations to rebalance the tree.

Features

The AVL tree is essentially a binary search tree, with the following characteristics:

  • Is a binary search tree
  • The absolute value (balance factor) of the difference between the height of the left and right subtrees of each node is at most 1.

The figure below is an AVL tree, and each node is marked with a balance factor: the

height of the left subtree of node 4 is 0, and the right subtree does not exist, so the balance factor is 0-(-1) = 1; all leaves The node does not have left and right subtrees, so the balance factor is 0.

For the above AVL tree, if 0 is inserted, then the binary tree at this time is:

The balance factor of node 4 is 2, which breaks the balance of the AVL tree. So how to restore the balance of AVL? Only need two operations of left rotation and right rotation to complete.

Spin

The rotation of the AVL tree is divided into four cases, namely left-left type, right-right type, left-right type, and right-left type.

Left-left

For the situation where the nodes in the graph are biased to the left, it is called the left-left type. At this time, we perform a right-rotation operation on node 4 to restore its balance.

Right rotation: Rotate two nodes clockwise so that parent node 4 is replaced by its own left child node 1, and node 4 becomes the right child node of node 1.

Here is an example:

the balance factor of node 6 is 2, at this time, it is left-left type, and right-handed operation is performed. At this time, the right child of node 4 becomes the left child of node 6.

Right right type


The picture shows the right-to-right type, for left-hand operation

Right left type


The figure is right-left type. First, perform a right-handed operation on node 6, and then perform a left-handed operation on node 4.

Left and right


The figure shows the left and right type. First, perform a left-hand operation on node 2 and perform a right-hand operation on node 8.

Code

public class Node {
    
    
    int data;
    Node lchild;
    Node rchild;
    int height;

    public Node(int data) {
    
    
        this.data = data;
    }
}

public class AVLTree {
    
    
    private Node root;

    // 记录节点的高度
    private int height(Node node) {
    
    
        if (node == null) {
    
    
            return -1;
        } else {
    
    
            return node.height;
        }
    }

    // 右右型 左旋
    private Node L_Rotate(Node node) {
    
    
        Node temp;

        // 进行旋转
        temp = node.rchild;
        node.rchild = temp.lchild;
        temp.lchild = node;

        // 重新计算高度
        node.height = Math.max(height(node.lchild), height(node.rchild)) + 1;
        temp.height = Math.max(height(temp.lchild), height(temp.rchild)) + 1;

        return temp;
    }

    // 左左型 右旋
    private Node R_Rotate(Node node) {
    
    
        Node temp;

        // 进行旋转
        temp = node.lchild;
        node.lchild = temp.rchild;
        temp.rchild = node;

        // 重新计算高度
        node.height = Math.max(height(node.lchild), height(node.rchild)) + 1;
        temp.height = Math.max(height(temp.lchild), height(temp.rchild)) + 1;

        return temp;
    }

    // 左右型 先进行左旋在进行右旋
    private Node L_R_Rotate(Node node) {
    
    
        // 对左子节点进行左旋
        node.lchild = L_Rotate(node.lchild);

        // 对节点进行右旋
        return R_Rotate(node);
    }

    // 右左型 先进性右旋在进行左旋
    private Node R_L_Rotate(Node node) {
    
    
        // 对右子节点进行右旋
        node.rchild = R_Rotate(node.rchild);

        // 对节点进行左旋
        return L_Rotate(node);
    }

    public void insert(int data) {
    
    
        root = insert(data, root);
    }

    // 插入操作
    private Node insert(int data, Node node) {
    
    
        if (node == null) {
    
    
            node = new Node(data);
        } else if (data < node.data) {
    
    
            // 向左子节点递归插入
            node.lchild = insert(data, node.lchild);

            // 如果左子节点的高度比右子节点的高度大2 则进行旋转调整
            if (height(node.lchild) - height(node.rchild) == 2){
    
    
                if (data < node.lchild.data) {
    
      // 左左型
                    node = R_Rotate(node);
                } else {
    
       // 左右型
                    node = R_L_Rotate(node);
                }
            }
        } else if (data > node.data) {
    
    
            // 向右子节点递归插入
            node.rchild = insert(data, node.rchild);

            // 如果右子节点的高度比左子节点的高度大2 则进行旋转调整
            if (height(node.rchild) - height(node.lchild) == 2) {
    
    
                if (data > node.rchild.data) {
    
     // 右右型
                    node = L_Rotate(node);
                } else {
    
      // 右左型
                    node = R_L_Rotate(node);
                }
            }
        }
        // 如果 data = node.data 这个节点在树上存在 什么也不做

        node.height = Math.max(height(node.lchild), height(node.rchild)) + 1;
        return node;
    }

    // 中序遍历AVL树
    public void inOrder() {
    
    
        inOrder(root);
    }

    private void inOrder(Node node) {
    
    
        if (node != null) {
    
    
            inOrder(node.lchild);
            System.out.println(node.data);
            inOrder(node.rchild);
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_46122005/article/details/111052377