Algoritmos y Estructura de Datos

Árboles Red Black y principales operaciones


Los árboles rojinegros son una variante de los árboles binarios de búsqueda que se utilizan para mantener el árbol equilibrado y garantizar un rendimiento óptimo en las operaciones de inserción, eliminación y búsqueda. Un árbol rojinegro cumple con las siguientes propiedades:

  • Todos los nodos son rojos o negros.
  • La raíz del árbol es siempre negra.
  • Todos los hijos null de un nodo son siempre negros.
  • Si un nodo es rojo, sus hijos deben ser negros.
  • En cualquier camino desde un nodo hasta un nodo null, el número de nodos negros debe ser el mismo.
  • Para mantener estas propiedades y garantizar que el árbol siempre esté equilibrado, se realizan rotaciones y se cambian los colores de los nodos cuando se insertan o eliminan elementos del árbol. Esto permite que el árbol siempre tenga una altura logarítmica en función del número de nodos, lo que significa que las operaciones de inserción, eliminación y búsqueda tienen una complejidad de O(log n).

                        
    1. #include <iostream>
    2. const bool RED = true;
    3. const bool BLACK = false;
    4. struct Node {
    5. int data;
    6. bool color;
    7. Node *left, *right, *parent;
    8. Node(int data) : data(data) {
    9. color = RED;
    10. left = right = parent = nullptr;
    11. }
    12. };
    13. class RedBlackTree {
    14. private:
    15. Node *root;
    16. Node *nil;
    17. public:
    18. RedBlackTree() {
    19. nil = new Node(0);
    20. nil->color = BLACK;
    21. nil->left = nil->right = nil->parent = nil;
    22. root = nil;
    23. }
    24. void LeftRotate(Node *&, Node *&);
    25. void RightRotate(Node *&, Node *&);
    26. void InsertFixup(Node *&, Node *&);
    27. void Insert(Node *&, Node *&, int);
    28. void Inorder(Node *&);
    29. void LevelOrder(Node *&);
    30. };
    Inserción:
  • Creamos un nuevo nodo con la clave que queremos insertar y lo insertamos en el árbol como lo haríamos en un árbol binario de búsqueda.
  • Luego, corregimos cualquier violación de las propiedades del árbol rojinegro que pueda haberse producido durante la inserción. Esto implica realizar rotaciones y cambiar los colores de los nodos según sea necesario.
  • Eliminación:
  • Buscamos el nodo que queremos eliminar en el árbol. Si no lo encontramos, no hay nada que eliminar.
  • Eliminamos el nodo del árbol como lo haríamos en un árbol binario de búsqueda.
  • Corregimos cualquier violación de las propiedades del árbol rojinegro que pueda haberse producido durante la eliminación. Esto implica realizar rotaciones y cambiar los colores de los nodos según sea necesario.
  • Búsqueda:
  • Comenzamos en la raíz del árbol y comparamos la clave que estamos buscando con la clave del nodo actual.
  • Si son iguales, hemos encontrado el nodo y devolvemos su dirección.
  • Si la clave que estamos buscando es menor que la clave del nodo actual, buscamos en el hijo izquierdo del nodo. Si es mayor, buscamos en el hijo derecho.
  • Si llegamos a un nodo null sin encontrar la clave, significa que la clave no se encuentra en el árbol y devolvemos null.
  • Link de apoyo

  • Introducción al arbol rojinegro
  • Árbol rojinegro