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
á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:
- 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
Girando a la izquierda. Solo podemos poner rojo el enlace de la izquierda ,
pero
aparecerá la siguiente situación:
Esto viola la regla 1 del árbol rojo-negro , por lo que todavía tenemos que operar, luego realizar la mano derecha
|
|
|
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
.
Echemos un vistazo a esta figura en este momento: ¿Hay el mismo lugar (piense en el 4 de arriba) -Nodo)
Ahora continúe operando en este nodo:
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
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;
}
}