Explicación de la estructura de datos del árbol rojo-negro (con código de implementación de Java)

2-3 definición de árbol de búsqueda

1. La longitud de la ruta de cualquier enlace vacío al nodo raíz es igual.
2. Cuando el 4-nodo se transforma en un 3-nodo, la altura del árbol no cambiará, solo cuando el nodo raíz es un 4-nodo temporal, Después de descomponer el nodo raíz, la altura del árbol es +1
3. El árbol de búsqueda binario ordinario crece de arriba a abajo, y el crecimiento de abajo hacia arriba del
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
árbol de búsqueda 2-3 es el árbol de búsqueda 2-3
(generado durante el proceso de inserción del nodo) 4- ¡El nodo es temporal!)

Definición árbol rojo-negro

Con la premisa de satisfacer el árbol de búsqueda 2-3, use la == "marca" == para el enlace entre los nodos.
Hay dos colores:
rojo Simular el 3-nodo en el árbol de búsqueda 2-3
negro Formulario de enlace de nodo ordinario

naturaleza:

  1. Los enlaces rojos son todas conexiones izquierdas
    2. Ningún nodo está conectado a dos enlaces rojos al mismo tiempo (4 nodos no existen)
    3. Cualquier enlace vacío al nodo raíz pasa por el mismo enlace negro

De esta manera, el árbol rojo-negro puede mantener un maravilloso equilibrio mientras inserta nodos.
Con este conocimiento, ¡comience a construir su propio árbol rojo-negro!

Mano izquierda y derecha

Cuando el nodo hijo izquierdo de un nodo es negro y el nodo hijo derecho es rojo, debe ser zurdo. Por
ejemplo, en la figura siguiente, inserte un nodo con un valor de 50
Inserte la descripción de la imagen aquí

Girando a la izquierda. Solo podemos poner rojo el enlace de la izquierda ,
pero
aparecerá la siguiente situación:

Inserte la descripción de la imagen aquí
Esto viola la regla 1 del árbol rojo-negro , por lo que todavía tenemos que operar, luego realizar la mano derecha
|
|
|
Inserte la descripción de la imagen aquí
Pero encontramos que aún viola la regla 2,
así que continúe operando

Inversión de color

La operación anterior produce dos nodos enlace rojo (4- correspondiente al nodo en el árbol binario), en este momento, necesitamos continuar operando este nodo con el fin de satisfacer la regla 2 .
Mira el siguiente este Figura Después de
insertar S, se forma AES (4 nodos) y luego se descomponen los 4 nodos
Inserte la descripción de la imagen aquí
.
Inserte la descripción de la imagen aquí
Echemos un vistazo a esta figura en este momento: ¿Hay el mismo lugar (piense en el 4 de arriba) -Nodo)
Inserte la descripción de la imagen aquí
Ahora continúe operando en este nodo:
Inserte la descripción de la imagen aquí
Al ver esto, es posible que se sienta un poco confundido: ¿Por qué los dos enlaces rojos son negros?
No se preocupe, vea a continuación

Si hay un nodo con 50 elementos, el
Inserte la descripción de la imagen aquí
resultado es diferente. Esto se debe a que estipulamos: El enlace del nodo raíz siempre apunta a sí mismo, y el enlace raíz siempre es negro.
Mira aquí, lo que el código debe lograr es encontrar la posición para insertar el elemento. Y coloque el nodo, y sucesivamente ** (zurdo, diestro, inversión de color) ------ (si es necesario) ** puede mantener el equilibrio del árbol rojo y negro
Código:

Código de implementación de Java

package cn.datastructure.structure.tree;

/**
 * @author 悠一木碧
 * 红黑树实现:
 * 基于了2-3查找树的思想:
 * 任意空链接到根节点的路径长度都是相等的
 * 4-结点变换为3-结点时, 树的高度不会发生变化, 只有当根节点是临时的4-结点时, 分解根节点后, 树的高度+1
 * 普通二叉查找树是自顶向下生长的, 2-3查找树的自底向上生长的
 * 且:
 * 红链接均为左连接
 * 没有任何一个结点同时与两个红链接相连
 * 任意空链接到根节点的路径经过相同的黑链接
 */
public class RedBlackTree<Key extends Comparable<Key>, Value> {
    
    
    private Node root;
    private int size;
    private final boolean RED = true;
    private final boolean BLACK = false;

    private class Node{
    
    
        public Key key;
        public Value value;
        public Node left;
        public Node right;
//        用来标识父节点指向自己链接的颜色
        public boolean color;

        public Node(Key key, Value value, Node left, Node right, boolean color) {
    
    
            this.key = key;
            this.value = value;
            this.left = left;
            this.right = right;
            this.color = color;
        }

        public Node() {
    
    
        }

    }


//  将根链接的颜色永远设置为黑色
    public void put(Key key, Value value){
    
    
        root = put(root, key, value);
        this.root.color = BLACK;
    }

//  在node结点下完成插入操作, 是个递归方法
    private Node put(Node node, Key key, Value value){
    
    
        if(null == node){
    
    
            size++;
            return new Node(key, value, null, null, BLACK);
        }
        if(key.compareTo(node.key) < 0){
    
    
            node.left = put(node.left, key, value);
        } else if(key.compareTo(node.key) > 0){
    
    
            node.right = put(node.right, key, value);
        } else{
    
    
            node.value = value;
        }

        if(isRed(node.right) && !isRed(node.left)){
    
    
            rotateLeft(node);
        }
        if(isRed(node.left) && isRed(node.left.left)){
    
    
            rotateRight(node);
        }
        if(isRed(node.left) && isRed(node.right)){
    
    
            colorInversion(node);
        }
        return node;
    }

    /**
     * 左旋操作,
     * @param head
     */
    private Node rotateLeft(Node head){
    
    
        Node rightSon = head.right;
        head.right = rightSon.left;
        rightSon.left = head;
        rightSon.color = head.color;
        head.color = RED;
        return rightSon;
    }

    /**
     * 右旋操作
     * @param head
     * @return
     */
    private Node rotateRight(Node head){
    
    
        Node leftSon = head.left;
        head.left = leftSon.right;
        leftSon.right = head;
        leftSon.color = head.color;
        head.color = RED;
        return leftSon;
    }

    /**
     * 空链接默认为黑色
     * @param node
     * @return
     */
    private boolean isRed(Node node){
    
    
        if(null == node){
    
    
            return false;
        }
        return node.color == RED;
    }


    /**
     * 相当于拆分掉4-结点, 在红黑树中, 临时的4-结点相当于当前结点的左右链接都是红色
     * @param node
     */
    private void colorInversion(Node node){
    
    
        node.color = RED;
        node.left.color = BLACK;
        node.right.color = BLACK;
    }




    public Value get(Key key){
    
    
        return get(root, key);
    }

    private Value get(Node node, Key key){
    
    
        if(null == node){
    
    
            return null;
        }

        int res = key.compareTo(node.key);

        if(res > 0){
    
    
            return get(node.right, key);
        } else if(res < 0){
    
    
            return get(node.left, key);
        } else{
    
    
            return node.value;
        }
    }



    public int size(){
    
    
        return size;
    }

}

Supongo que te gusta

Origin blog.csdn.net/Valishment/article/details/109319469
Recomendado
Clasificación