Zrównoważone drzewa wyszukiwania binarnego są niezbędne do zagwarantowania wyszukiwania O (log n) (lub podobnych operacji). W dynamicznym środowisku, w którym wiele kluczy jest losowo wstawianych i / lub usuwanych, drzewa mogą zdegenerować się do połączonych list, które są straszne przy wyszukiwaniu. Tak więc istnieją różne rodzaje równoważących się drzew binarnych, które przeciwdziałają temu efektowi (takie jak drzewa AVL lub drzewa rozrośnięte ). Drzewa te są oparte na różnych rodzajach rotacji, które ponownie równoważą drzewo.
Rotacje
W tym wyzwaniu przyjrzymy się tylko pojedynczym obrotom w prawo, taki obrót (obrót w lewo byłby symetryczny) wygląda następująco:
5 3
/ \ / \
3 6 => 1 5
/ \ / \
1 4 4 6
Jeżeli którykolwiek z liści 1
, 4
lub 6
miał prawo sub-trees lewo lub obrót po prostu trzymać je tam. Jeśli jest to poddrzewo większego drzewa, po prostu „odetniemy” go w węźle 5
i „ponownie dołączymy” obrócone drzewo (teraz węzeł 3
) do tego węzła.
Wyzwanie
Biorąc pod uwagę drzewo wyszukiwania binarnego 1 i klucz, obróć drzewo w tym węźle, jak opisano powyżej. Kluczem podanym w powyższym przykładzie byłoby 5
.
Reguły i I / O
- możesz użyć dowolnego typu dla kluczy, o ile istnieje sprzeczność między kluczami wybranymi przez ciebie a kluczami przypadków testowych
- możesz wybrać dowolną reprezentację dla drzew binarnych, o ile nie ma dwuznaczności (np.
[3,[]]
jest niejednoznaczna, chyba że określono inaczej) i jest to naturalne dla wybranego języka - ponieważ dane wejściowe będą zawsze drzewem wyszukiwania binarnego, nie ma duplikatów kluczy
- możesz założyć, że klucz jest zawarty w drzewie
- możesz założyć, że węzeł zawierający klucz ma lewe dziecko
- możesz nie przyjąć właściwą poddrzewo pod warunkiem kluczem
- możesz nie przyjąć, że drzewo jest niezrównoważony przed obrotem
- możesz nie przyjąć, że drzewo jest równoważony po obrocie
- możesz użyć dowolnej domyślnej metody We / Wy
- Twoje zgłoszenie może być funkcją zwracającą drzewo lub pełny program drukujący rozwiązanie
Przypadki testowe
Te przykłady przedstawiają drzewo w następujący sposób
- jeśli to liść:
[]
- jeśli jest to drzewo z kluczem,
x
a oba poddrzewa są liśćmi:[x]
- jeśli jest to drzewo z kluczem
x
i poddrzewamileft
right
:[x,left,right]
Pierwszym przykładem jest ten przedstawiony w sekcji Obroty . Jeśli z jakiegoś powodu potrzebujesz ich graficznej reprezentacji, oto 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: co oznacza, że dla dowolnego węzła wszystkie klucze w lewym poddrzewie będą mniejsze niż ten klucz, a wszystkie klucze w prawym poddrzewie będą większe niż ten
2: aby zapobiec gniciu linków, umieściłem je jako komentarz
data B=B[B]Int
pozwoliłoby zaoszczędzić trochę więcej bajtów.k<n=B[k!l,r]n
a następniek>n=B[l,k!r]n
w jeden:,k/=n=B[k!l,k!r]n
a następnie dodając,k!x=x
aby dopasowanie wzorca było wyczerpujące.Vim , 25 bajtów
Pobiera dane wejściowe do bufora - klawisz i drzewo oddzielone spacjami. Oczekuje się, że drzewo będzie reprezentowane w następujący sposób:
[]
k
, lewym dzieckiem<left>
i prawym dzieckiem<right>
:[ k <left><right>]
Nie
k
ważne są spacje wokół klucza , takie rozwiązanie działa w przypadku dowolnych drzew.Wypróbuj online!
Wyjaśnienie
Zapowiedź
Oto podgląd pierwszego przypadku testowego wygenerowanego przez ten skrypt przez Lynn :
źródło
Wolfram Language (Mathematica) , 30 bajtów
Wypróbuj online!
Drzewo reprezentowane w następujący sposób:
$
(możesz go zastąpić dowolną wartością, która nie jest kluczem)x
i poddrzewamileft
right
:x[left,right]
Na przykład drzewo w pierwszym przypadku testowym jest reprezentowane przez
5[3[1[$,$],4[$,$]],6[$,$]]
.Wyjaśnienie:
źródło
Common Lisp, 146 bajtów
Wypróbuj online lub sprawdź wszystkie przypadki testowe!
Drzewo jest reprezentowane w następujący sposób:
nil
(lub równoważnie w Common Lisp jako pusta lista()
)(node left-subtree right-subtree)
(więc liśćL
jest reprezentowany jako(L nil nil)
).źródło
JavaScript (Node.js) , 70 bajtów
Wypróbuj online! Link zawiera przypadki testowe. Wszystkie węzły muszą mieć lewy i prawy wpis, ale mogą
[]
wskazywać brak poddrzewa po tej stronie. Jako skrót zestaw testów używal(N)
do wskazania, żeN
jest liściem il(N,L)
do wskazania, żeN
ma lewe poddrzewo,L
ale nie ma prawego poddrzewo zarówno na wejściu, jak i na wyjściu.źródło
Python 2 , 85 bajtów
Wypróbuj online!
Format wejściowy:
[KEY, LEFT_SUBTREE, RIGHT_SUBTREE]
[]
źródło
Galaretka , 24 bajty
Wypróbuj online!
Ostrzeżenie: zwykle górna linia nie powinna istnieć, a dolna linia powinna mieć a
ß
, a nieç
. Jednak sprytne sztuczki łańcuchowe iß
nie pasują do siebie z powoduß
zmienna aria. Technicznie rzecz biorąc, mógłbym nadal pominąć górną linię, ale wtedy wynik musiałby być pełnym programem, ponieważ w przeciwnym razie musiałby być włączony jako osobna linia w dowolnym programie, co nie jest możliwe, chyba że mają szczęście. Oznacza to, że niestety dane wyjściowe miałyby dwuznaczną reprezentację, ponieważ po przesłaniu pełnego programu liczy się to, co faktycznie otrzymuje, a nie wynik techniczny przed zamknięciem programu. Aby nie robić bałaganu zarówno z rekurencją, jak i odpowiednią reprezentacją ciągu, postanowiłem przesłać funkcję 2-liniową, w której zadaniem górnej linii jest wywołanie dolnej. Konsekwencja? Ogromna strata 2 cennych i cennych bajtów. W obronie Jelly (i Dennisa, a także każdego innego uczestnika),źródło