Árbol binario de autoequilibrio AVI

Árbol binario equilibrado

  • Esencialmente una especie de árbol de búsqueda binaria

  • El valor absoluto (factor de equilibrio) de la diferencia de altura entre los subárboles izquierdo y derecho de cada nodo es como máximo 1, | leftTreeHeightmax-rightTreeHeightmax | <= 1

  • diagrama de árbol avi (cuando el subárbol izquierdo o el subárbol derecho, está vacío, el valor predeterminado es -1)

    alfiler
    Cuando varios nodos se vuelven más

Girar

  • Cuando el factor de equilibrio de avi es mayor que 1, el equilibrio de avi se romperá. En este momento, debemos rotar hacia la izquierda o hacia la derecha para reequilibrarlo.

  • La rotación de AVI se divide en cuatro casos, a saber, tipo izquierda-izquierda, tipo derecha-derecha, tipo izquierda-derecha, tipo derecha-izquierda

  • Tipo de izquierda a izquierda: como en la figura, todos los nodos están sesgados hacia la izquierda, esta vez tenemos que rotar a la derecha

    Inserte la descripción de la imagen aquí
    Rotación a la derecha: gire dos nodos en el sentido de las agujas del reloj para que el nodo padre 4 sea reemplazado por el nodo izquierdo 1 y el nodo 4 se convierta en el nodo derecho del nodo 1. ( Resumen: un nodo con un factor de equilibrio de 2 se convierte en el subárbol derecho de su subárbol izquierdo, y el subárbol derecho del subárbol izquierdo original se convierte en su subárbol izquierdo. El factor de equilibrio se actualiza nuevamente )
    Inserte la descripción de la imagen aquí

  • Los nodos de tipo derecho-derecho se concentran en la derecha y se requiere la operación con la mano izquierda ( el punto con un factor de equilibrio de 2 se convierte en el subárbol izquierdo de su subárbol derecho, y el subárbol izquierdo del subárbol derecho original se convierte en su subárbol derecho )

    Inserte la descripción de la imagen aquí

  • Tipo de derecha a izquierda: primero seleccione diestro (conviértalo en tipo de derecha a derecha), luego gírelo para zurdo ( primero conviértalo en tipo de derecha a derecha y luego trate con el tipo de derecha a derecha )

    Inserte la descripción de la imagen aquí

  • Tipo de izquierda a derecha: primero cámbielo a tipo de izquierda a izquierda

    Inserte la descripción de la imagen aquí

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);
        }
    }
}

Supongo que te gusta

Origin blog.csdn.net/qq_45788043/article/details/112600527
Recomendado
Clasificación