Rotación del árbol rojo-negro: cuando tengo y = x.right; x.right = y.izquierda. ¿Es lo mismo escribir y.left.p = x como x.right.p = x

8

En CLRS, los autores introducen la operación de rotación en el árbol rojo-negro siguiendo el pseudocódigo: Rotación izquierda

LEFT-ROTATE(T, x)

    y = x.right        # Line 1
    x.right = y.left   # Line 2
    if y.left ≠ T.nil  # Line 3
        y.left.p = x   # Line 4
    y.p = x.p
    if x.p == T.nil
        T.root = y
    elseif x == x.p.left
        x.p.left = y
    else x.p.right = y
    y.left = x
    x.p = y

donde atributo .left, .right, .p correspondiente a su hijo izquierdo, derecho y su padre. T es el árbol.

Mis preguntas principales se encuentran en la línea 3 y la línea 4:

  1. ¿Por qué necesito tener la condición if de la línea 3? El libro dice que NIL es en realidad una hoja del árbol rojo-negro, por lo que supongo que NIL también puede tener un puntero principal. Estos códigos aún deberían funcionar sin la Línea 3.

  2. Con la línea 1 y la línea 2, ¿puedo escribir la línea 4 como x.right.p = x? Si en realidad son lo mismo, ¿hay alguna razón por la cual el autor eligió escribirlo y.left.p = x?

Mi instinto es que x.right.p = xes diferente de y.left.p = x. Sin embargo, no puedo encontrar una buena explicación para esto. He revisado la definición de punteros , pero sigue siendo bastante confuso después de buscar en Google mucho ...

cindy50633
fuente

Respuestas:

3

ingrese la descripción de la imagen aquí

Nota: No puse la flecha de relación de padres en cada diagrama para eliminar el desorden.

El nodo nulo no puede tener padres, como muestra el diagrama. Hay más explicaciones en profundidad aquí.

  1. como muestra el diagrama, la verificación en la línea 3 no es necesaria, si y.leftNUNCA es nula. Si esto no está garantizado, esta comprobación es para evitar un "error" de desreferencia de puntero nulo.

  2. La elección de uso y.left.p = xes la preferencia del usuario. Para mí, es mucho más claro. Estamos haciendo el "y left subtree into x right subtree".

El ejemplo que mostró @HolderRoy funcionará, pero hace una asignación adicional para posiblemente almacenar el y.leftpuntero, para cada llamada de función.

Sr. vea
fuente
¿Hay alguna razón por la que un nodo nulo no tenga puntero principal? Reviso el libro de esta sección nuevamente. Sin embargo, no aborda esta propiedad en absoluto.
cindy50633
1
@ cindy50633 null muestra que la variable / propiedad se inicializó, pero no hay una dirección a la que apunte, por lo que no tendría ninguna estructura o propiedades. La estructura que contiene la propiedad parentno existe, por lo parentque no existe.
Sr.vea
2

Después de leer la última línea de su descripción, me di cuenta de que no aprendió punteros, por lo que quizás le resulte difícil entender por qué debemos juzgar si algo es T.nil. Pero aún trato de responder a su pregunta, espero poder explicarla claramente.

  1. En términos de estructura de datos, seguramente no necesita la Línea 3, debe ajustar y.left.p en cualquier caso.

    Sin embargo, para un lenguaje dado, solo use C / C ++ como ejemplo, usamos NULL o nullptr para la hoja y el padre de la raíz, lo que significa que no es nada. Ahora que lo pienso, ¿es necesario costarle a la memoria tantos nodos de árbol como para salvar hojas inútiles? Por supuesto no. Así que lo marcamos como puntero NULL, lo que no significa nada, y además no tiene p, izquierda o derecha.

    Se llega a la conclusión de que depende de su implementación si debe juzgar a T.nil en la línea 3.

  2. Sí tu puedes. después x.right = y.left, x.right e y.left es temporalmente la misma cosa, por lo que x.right.p y y.left.p son lo mismo.

    Para la línea 2 ~ 4, también puede escribir así:

beta = y.left;
x.right = beta; 
if beta != T.nil
    beta.p = x;
HolderRoy
fuente