Binäre Baumrotationen

16

Ausgeglichene binäre Suchbäume sind wichtig, um O (log n) -Nachschauen (oder ähnliche Operationen) zu gewährleisten . In einer dynamischen Umgebung, in der viele Schlüssel nach dem Zufallsprinzip eingefügt und / oder gelöscht werden, können Bäume zu verknüpften Listen ausarten, die für Nachschlagezwecke schrecklich sind. Daher gibt es verschiedene Arten von sich selbst ausgleichenden Binärbäumen, die diesem Effekt entgegenwirken (z. B. AVL-Bäume oder Splay-Bäume ). Diese Bäume basieren auf verschiedenen Arten von Rotationen , die den Baum wieder ins Gleichgewicht bringen.

Drehungen

In dieser Herausforderung werden nur einzelne Rechtsdrehungen betrachtet. Eine solche Drehung (Linksdrehung wäre symmetrisch) sieht folgendermaßen aus:

    5            3
   / \          / \
  3   6   =>   1   5
 / \              / \
1   4            4   6

Wenn eines der Blätter 1, 4oder 6verlassen hatte oder rechten Teilbäume wäre eine Drehung einfach halten sie dort. Wenn dies ein Teilbaum eines größeren Baums ist, würden wir ihn einfach am Knoten "abschneiden" 5und den gedrehten Baum (jetzt Knoten 3) an diesen Knoten "anhängen" .

Herausforderung

Wenn ein binärer Suchbaum 1 und ein Schlüssel gegeben sind, drehen Sie den Baum auf diesem Knoten nach rechts, wie oben beschrieben. Der im obigen Beispiel angegebene Schlüssel wäre 5.

Regeln und I / O

  • Sie können einen beliebigen Schlüsseltyp verwenden, solange zwischen den Schlüsseln Ihrer Wahl und den Schlüsseln der Testfälle ein Unterschied besteht
  • Sie können eine beliebige Darstellung für Binärbäume auswählen, [3,[]]sofern keine Mehrdeutigkeit vorliegt (z. B. ist sie mehrdeutig, sofern nicht anders angegeben) und dies für die Sprache Ihrer Wahl natürlich ist
  • da die Eingabe immer ein binärer Suchbaum ist, gibt es keine doppelten Schlüssel
  • Sie können davon ausgehen, dass der Schlüssel im Baum enthalten ist
  • Sie können davon ausgehen, dass der Knoten, der den Schlüssel enthält, ein linkes Kind hat
  • Sie können keinen rechten Teilbaum unter dem angegebenen Schlüssel annehmen
  • Sie können nicht davon ausgehen, dass der Baum vor der Drehung aus dem Gleichgewicht geraten ist
  • Sie können nicht davon ausgehen, dass der Baum nach der Drehung ausgeglichen ist
  • Sie können eine beliebige Standard-E / A-Methode verwenden
  • Ihre Eingabe kann eine Funktion sein, die den Baum zurückgibt, oder ein vollständiges Programm, das die Lösung druckt

Testfälle

Diese Beispiele stellen einen Baum wie folgt dar

  • Wenn es ein Blatt ist: []
  • Wenn es sich um einen Baum mit Schlüssel handelt xund beide Teilbäume Blätter sind:[x]
  • Wenn es sich um einen Baum mit Schlüssel xund Teilbäumen handelt left right:[x,left,right]

Das erste Beispiel finden Sie im Abschnitt Rotationen . Wenn Sie aus irgendeinem Grund eine grafische Darstellung benötigen, klicken Sie hier 2 .

5 [5,[3,[1],[4]],[6]]  ->  [3,[1],[5,[4],[6]]]
5 [5,[3,[1],[4]],[]]  ->  [3,[1],[5,[4],[]]]
5 [5,[3,[],[4]],[6]]  ->  [3,[],[5,[4],[6]]]
5 [5,[3,[1],[]],[]]  ->  [3,[1],[5]]
4 [8,[4,[2,[1],[3]],[6,[5],[7]]],[12,[10,[9],[11]],[14,[13],[15]]]]  ->  [8,[2,[1],[4,[3],[6,[5],[7]]]],[12,[10,[9],[11]],[14,[13],[15]]]]
8 [10,[8,[6,[4,[2,[],[3]],[5]],[7]],[9]],[11]]  ->  [10,[6,[4,[2,[],[3]],[5]],[8,[7],[9]]],[11]]
10 [10,[8,[6,[4,[2,[],[3]],[5]],[7]],[9]],[11]]  ->  [8,[6,[4,[2,[],[3]],[5]],[7]],[10,[9],[11]]]
9 [6,[3,[2],[5]],[9,[8],[12,[11],[15,[14],[]]]]]  ->  [6,[3,[2],[5]],[8,[],[9,[],[12,[11],[15,[14],[]]]]]]
7 [7,[5,[3,[1],[4]],[6]],[8]]  ->  [5,[3,[1],[4]],[7,[6],[8]]]
15 [17,[9,[5,[2,[0],[4]],[8]],[15,[13,[11,[10],[12]],[14]],[16]]],[40,[27,[21,[19,[18],[20]],[24,[22],[25]]],[28]],[44,[42,[41],[]],[51,[47],[59,[55],[61]]]]]]  ->  [17,[9,[5,[2,[0],[4]],[8]],[13,[11,[10],[12]],[15,[14],[16]]]],[40,[27,[21,[19,[18],[20]],[24,[22],[25]]],[28]],[44,[42,[41],[]],[51,[47],[59,[55],[61]]]]]]
21 [17,[9,[5,[2,[0],[4]],[8]],[15,[13,[11,[10],[12]],[14]],[16]]],[40,[27,[21,[19,[18],[20]],[24,[22],[25]]],[28]],[44,[42,[41],[]],[51,[47],[59,[55],[61]]]]]]  ->  [17,[9,[5,[2,[0],[4]],[8]],[15,[13,[11,[10],[12]],[14]],[16]]],[40,[27,[19,[18],[21,[20],[24,[22],[25]]]],[28]],[44,[42,[41],[]],[51,[47],[59,[55],[61]]]]]]

1: Dies bedeutet, dass für jeden Knoten alle Schlüssel im linken Teilbaum kleiner als dieser Schlüssel sind und alle Schlüssel im rechten Teilbaum größer als dieser Schlüssel sind

2: um link-rot zu verhindern, habe ich sie als kommentar eingebettet

ბიმო
quelle

Antworten:

8

Haskell , 93 92 84 83 82 Bytes

data B=B[B]Int|L
k!B[l@(B[x,y]a),r]n|k<n=B[k!l,r]n|k>n=B[l,k!r]n|1>0=B[x,B[y,r]k]a

Vielen Dank an @BMO, @alephalpha und @Laikoni für jeweils ein Byte und @nimi für acht Bytes!

Probieren Sie es online!

Angs
quelle
Durch data B=B[B]Intdie Verwendung von würden weitere Bytes eingespart.
Laikoni
@Laikoni nur ein Byte, denke ich, aber ich nehme es
Angs
Sie können 2 Bytes sparen, indem Sie zuerst die beiden Fälle k<n=B[k!l,r]nund dann k>n=B[l,k!r]n: zu einem zusammenführen k/=n=B[k!l,k!r]nund dann hinzufügen k!x=x, um den Mustervergleich vollständig zu gestalten.
Radek
5

Vim , 25 Bytes

Übernimmt die Eingabe in den durch Pufferspeicher getrennten Schlüssel und Baum. Es wird erwartet, dass der Baum wie folgt dargestellt wird:

  • Blatt: []
  • Knoten mit Schlüssel k, linkes Kind <left>und rechtes Kind <right>:[ k <left><right>]

Nicht die Leerzeichen um den Schlüssel, kdie wichtig sind, damit die Lösung für beliebige Bäume funktioniert.

"adw/ <C-r>a⏎3dw%l"apr[%xl%i]

Probieren Sie es online!

Erläuterung

"adw                           " delete the key and trailing space, keep in register a
    / <C-r>a⏎                  " move cursor to the key surrounded with spaces
             3dw               " remove key and [ (move left node to top)
                %l             " move cursor to the right subtree
                  "ap          " insert key there
                     r[        " insert a [ (appending subtree to key)
                       %       " move to the end of new left subtree
                        x      " remove ] (fix parentheses)
                         l%    " move to the end of new right subtree
                           i]  " insert ] (fix parentheses)

Vorschau

Hier ist eine Vorschau des ersten Testfalls, der mit diesem Skript von Lynn generiert wurde :

                       Vim Vorschau

ბიმო
quelle
3

Wolfram Language (Mathematica) , 30 Byte

#2/.a_~b_~c_~#~d_:>b[a,c~#~d]&

Probieren Sie es online!

Ein Baum wie folgt dargestellt:

  • Wenn es ein Blatt ist: $(Sie können es durch einen beliebigen Wert ersetzen, der kein Schlüssel ist.)
  • Wenn es sich um einen Baum mit Schlüssel xund Teilbäumen handelt left right:x[left,right]

Zum Beispiel wird der Baum im ersten Testfall durch dargestellt 5[3[1[$,$],4[$,$]],6[$,$]].

Erläuterung:

#2                                the second input
  /.                              replace
    a_~b_~c_~#~d_                 #[b[a,c],d], where # is the first input
                 :>               by
                   b[a,c~#~d]     b[a,#[c,d]]
                             &    define a function
Alephalpha
quelle
3

Common Lisp, 146 Bytes

(defun r(k a)(cond((not a)a)((=(car a)k)`(,(caadr a),(cadadr a)(,(car a),(car(cddadr a)),(caddr a))))(t`(,(car a),(r k(cadr a)),(r k(caddr a))))))

Probieren Sie es online aus oder überprüfen Sie alle Testfälle!

Ein Baum wird wie folgt dargestellt:

  • ein leerer Baum wird dargestellt als nil(oder äquivalent in Common Lisp als leere Liste ())
  • Ein nicht leerer Baum wird als Liste von drei Elementen dargestellt (node left-subtree right-subtree) (ein Blatt Lwird also als dargestellt (L nil nil)).
Renzo
quelle
2

JavaScript (Node.js) , 70 Byte

n=>f=a=>n-a[0]?(a[i=n<a[0]?1:2]=f(a[i]),a):(i=a[1],a[1]=i[2],i[2]=a,i)

Probieren Sie es online! Link enthält Testfälle. Alle Knoten müssen linke und rechte Einträge haben, aber sie können []auf dieser Seite keinen Unterbaum anzeigen. Als Abkürzung verwendet die Testsuite, l(N)um anzuzeigen, dass Nes sich um ein Blatt handelt, und l(N,L)um anzugeben, dass Nes Lsowohl bei der Eingabe als auch bei der Ausgabe einen linken Teilbaum, aber keinen rechten Teilbaum gibt.

Neil
quelle
2

Python 2 , 85 Bytes

R=lambda T,k:k in T and T[1][:2]+[[T[0],T[1][2],T[2]]]or T[:1]+[R(i,k)for i in T[1:]]

Probieren Sie es online!

Eingabeformat:

  • Baum: [KEY, LEFT_SUBTREE, RIGHT_SUBTREE]
  • Blatt: []
Erik der Outgolfer
quelle
1

Gelee , 24 Bytes

ñ
Ḣ,1ịṪƊṭ@ṪṭḢð{Ḣ;ç€ɗ¹¡i?

Probieren Sie es online!

Warnung: Normalerweise sollte die obere Zeile nicht vorhanden sein und die untere Zeile sollte ein ß, kein a haben ç. Clevere Kettentricks passen ßaber nicht gut zusammen, bedingt durchß's variable Arität. Technisch hätte ich die oberste Zeile noch weglassen können, aber dann hätte das Ergebnis ein vollständiges Programm sein müssen, da es sonst in der Lage sein müsste, als eigene Zeile in jedes Programm aufgenommen zu werden, was ohne Sie nicht möglich ist hab Glück. Dies bedeutet, dass die Ausgabe leider mehrdeutig dargestellt worden wäre, da bei der Übermittlung eines vollständigen Programms die tatsächliche Ausgabe zählt und nicht das technische Ergebnis, bevor das Programm geschlossen wird. Um die Rekursion und die korrekte Darstellung von Zeichenfolgen nicht zu verfälschen, habe ich beschlossen, eine 2-Zeilen-Funktion einzureichen, bei der die oberste Zeile nur die unterste aufruft. Die Konsequenz? Eine riesige Verschwendung von 2 wertvollen und wertvollen Bytes. Zur Verteidigung von Jelly (und Dennis sowie aller anderen Mitwirkenden)

Erik der Outgolfer
quelle