Rot-Schwarz-Baumrotation: Wenn ich y = x.right habe; x.right = y.left. Ist es dasselbe, y.left.p = x als x.right.p = x zu schreiben?

8

In CLRS führen die Autoren die Rotationsoperation in einem rot-schwarzen Baum durch folgenden Pseudocode ein: Linksdrehung

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

Wobei das Attribut .left, .right, .p seinem linken, rechten Kind und seinem Elternteil entspricht. T ist der Baum.

Meine Hauptfragen liegen in Zeile 3 und Zeile 4:

  1. Warum muss ich die if-Bedingung von Zeile 3 haben? Das Buch sagt, dass NIL tatsächlich ein Blatt des rot-schwarzen Baums ist, daher gehe ich davon aus, dass NIL auch einen übergeordneten Zeiger haben kann. Diese Codes sollten weiterhin ohne Zeile 3 funktionieren.

  2. Kann ich mit Zeile 1 und Zeile 2 Zeile 4 als schreiben x.right.p = x? Wenn sie tatsächlich gleich sind, gibt es einen Grund, als den der Autor sie geschrieben hat y.left.p = x?

Mein Instinkt ist, dass x.right.p = xdas anders ist als y.left.p = x. Ich kann jedoch keine gute Erklärung dafür finden. Ich habe die Definition von Zeigern überprüft , aber es ist immer noch ziemlich verwirrend, nachdem ich viel gegoogelt habe ...

cindy50633
quelle

Antworten:

3

Geben Sie hier die Bildbeschreibung ein

Hinweis: Ich habe nicht in jedem Diagramm einen Pfeil für die übergeordnete Beziehung eingefügt, um Unordnung zu vermeiden.

Der Nullknoten kann keine Eltern haben, wie das Diagramm zeigt. Es gibt mehr in die Tiefe Erklärung hier

  1. Wie das Diagramm zeigt, ist die Prüfung in Zeile 3 nicht erforderlich, wenn y.leftNIE null. Wenn dies nicht garantiert ist, soll durch diese Prüfung der Fehler "Nullzeiger-Dereferenzierung" verhindert werden.

  2. Die Wahl der Verwendung y.left.p = xist die Benutzerpräferenz. Für mich ist es viel klarer. Wir machen das "y left subtree into x right subtree".

Das gezeigte Beispiel @HolderRoy funktioniert, es wird jedoch eine zusätzliche Zuordnung vorgenommen, um möglicherweise den y.leftZeiger für jeden Funktionsaufruf zu speichern .

mr.vea
quelle
Gibt es einen Grund, warum ein Nullknoten keinen übergeordneten Zeiger hat? Ich überprüfe das Buch dieses Abschnitts noch einmal. Diese Eigenschaft wird jedoch überhaupt nicht angesprochen.
cindy50633
1
@ cindy50633 null zeigt an, dass die Variable / Eigenschaft initialisiert wurde, aber es gibt keine Adresse, auf die sie verweist, sodass sie keine Struktur oder Eigenschaften haben würde. Die Struktur, die die Eigenschaft parententhält, existiert nicht, existiert also parentnicht.
mr.vea
2

Nachdem ich die letzte Zeile Ihrer Beschreibung gelesen hatte, bemerkte ich, dass Sie keine Hinweise gelernt haben. Daher fällt es Ihnen möglicherweise schwer zu verstehen, warum wir beurteilen müssen, ob etwas T.nil ist. Aber ich versuche immer noch, Ihre Frage zu beantworten. Ich hoffe, ich kann sie klar erklären.

  1. In Bezug auf die Datenstruktur brauchen Sie sicherlich nicht Zeile 3, Sie müssen y.left.p auf jeden Fall anpassen.

    Verwenden Sie für eine bestimmte Sprache jedoch nur C / C ++ als Beispiel. Wir verwenden NULL oder nullptr für das übergeordnete Element von leaf und root, was bedeutet, dass es nichts ist. Denken Sie nur daran, ist es notwendig, Speicher so viele wie Baumknoten zu kosten, um nutzlose Blätter zu retten? Natürlich nicht. Also markieren wir es als NULL-Zeiger, was nichts bedeutet, und alse hat kein p, links oder rechts.

    Die Schlussfolgerung kommt, dass es von Ihrer Implementierung abhängt, ob Sie T.nil in Zeile 3 beurteilen sollten.

  2. Ja, du kannst. danach x.right = y.leftsind x.right und y.left vorübergehend dasselbe, also sind x.right.p und y.left.p genau dasselbe.

    Für Zeile 2 ~ 4 können Sie auch folgendermaßen schreiben:

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