Rotação em árvore vermelho-preto: Quando tenho y = x.right; x.right = y.left. É o mesmo que escrever y.left.p = x como x.right.p = x

8

No CLRS, os autores introduzem a operação de rotação na árvore vermelho-preto seguindo o pseudocódigo: Rotação Esquerda

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

em que atributo .left, .right, .p corresponde ao filho esquerdo, direito e pai. T é a árvore.

Minhas principais perguntas estão na Linha 3 e na Linha 4:

  1. Por que preciso ter a condição if da Linha 3? O livro diz que o NIL é na verdade uma folha da árvore vermelho-preta, então suponho que o NIL também possa ter um ponteiro pai. Esses códigos ainda devem funcionar sem a linha 3.

  2. Com a Linha 1 e a Linha 2, posso escrever a Linha 4 como x.right.p = x? Se eles são realmente iguais, existe uma razão pela qual o autor escolheu escrevê-lo como y.left.p = x?

Meu instinto é que x.right.p = xé diferente y.left.p = x. No entanto, não consigo encontrar uma boa explicação para isso. Eu verifiquei a definição de ponteiros , mas ainda é bastante confusa depois que pesquisei bastante no Google ...

cindy50633
fonte

Respostas:

3

insira a descrição da imagem aqui

Nota: Eu não coloquei seta de relacionamento com os pais em todos os diagramas para eliminar alguma confusão.

O nó nulo não pode ter pais, como mostra o diagrama. Há uma explicação mais aprofundada aqui

  1. como o diagrama mostra, a verificação na linha 3 não é necessária, se y.leftNUNCA for nulo. Se isso não for garantido, essa verificação será para evitar "erro de desreferenciação de ponteiro nulo".

  2. a escolha do uso y.left.p = xé a preferência do usuário. Para mim, é muito mais claro. Nós somos fazer o "y left subtree into x right subtree".

O exemplo mostrado pelo @HolderRoy funcionará, mas faz uma alocação adicional para possivelmente armazenar o y.leftponteiro, para cada chamada de função.

mr.vea
fonte
Existe algum motivo para um nó nulo não ter ponteiro pai? Verifico o livro desta seção novamente. No entanto, ele não trata dessa propriedade.
Cindy50633 04/04/19
1
@ cindy50633 null mostra que a variável / propriedade foi inicializada, mas não há um endereço para o qual aponta, portanto ela não teria nenhuma estrutura ou propriedades. A estrutura que contém a propriedade parentnão existe, portanto parentnão existe.
precisa saber é o seguinte
2

Depois de ler a última linha da sua descrição, notei que você não aprendeu dicas, então talvez seja difícil entender por que precisamos julgar se algo é T.nil. Mas ainda tento responder à sua pergunta, espero poder explicá-la claramente.

  1. Em termos de estrutura de dados, certamente você não precisa da Linha 3, é necessário ajustar y.left.p em qualquer caso.

    No entanto, para um determinado idioma, basta usar C / C ++ como exemplo, usamos NULL ou nullptr para o pai da folha e raiz, o que significa que não é nada. Basta pensar nisso, é necessário custar memória a tantos nós de árvore para salvar folhas inúteis? Claro que não. Por isso, marcamos como ponteiro NULL, o que não significa nada, e também não tem p, esquerda ou direita.

    Conclui-se que depende da sua implementação se você deve julgar T.nil na Linha 3.

  2. Sim você pode. depois x.right = y.left, x.right e y.left são temporariamente a mesma coisa; portanto, x.right.p e y.left.p são a mesma coisa.

    Para as linhas 2 a 4, você também pode escrever assim:

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