İkili ağaç dönüşleri


16

Dengeli ikili arama ağaçları O (log n) aramalarını (veya benzer işlemleri) garanti etmek için gereklidir . Çok sayıda anahtarın rastgele yerleştirildiği ve / veya silindiği dinamik bir ortamda, ağaçlar aramalar için korkunç olan bağlantılı listelere dönüşebilir. Bu nedenle, bu etkiye karşı koyan çeşitli kendini dengeleyen ikili ağaçlar vardır ( AVL ağaçları veya yayvan ağaçları gibi ). Bu ağaçlar , ağacı yeniden dengeleyen farklı rotasyon türlerine dayanmaktadır .

rotasyonlar

Bu meydan okumada sadece tek sağ dönüşlere bakacağız, böyle bir dönüş (sol dönüş simetrik olacaktır) şöyle görünür:

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

Yaprakların Varsa 1, 4ya 6bırakmıştı veya sağ alt ağaçlar bir rotasyon sadece onları orada tutmak olacaktır. Bu daha büyük bir ağacın alt ağacı ise, sadece düğümü 5"keseriz" ve döndürülen ağacı (şimdi düğüm 3) o düğüme "yeniden ekleriz" .

Meydan okuma

Bir ikili arama ağacı 1 ve bir anahtar verildiğinde, bu düğüm üzerindeki ağacı yukarıda açıklandığı gibi sağa döndürün. Yukarıdaki örnekte verilen anahtarı olacaktır 5.

Kurallar ve G / Ç

  • seçtiğiniz tuşlar ile test senaryolarının tuşları arasında bir bağlantı olduğu sürece tuşlar için herhangi bir tür kullanabilirsiniz.
  • [3,[]]belirsizlik olmadığı sürece (örn. aksi belirtilmedikçe belirsiz) ve seçtiğiniz dil için doğal olan ikili ağaçlar için herhangi bir temsili seçebilirsiniz.
  • giriş her zaman ikili bir arama ağacı olacağından yinelenen anahtar yoktur
  • anahtarın ağaçta olduğunu varsayabilirsiniz.
  • anahtarı içeren düğümün sol çocuğu olduğunu varsayabilirsiniz.
  • Eğer açabilir değil sağlanan anahtarının altında sağ alt ağacı varsayalım
  • Eğer açabilir değil ağaç dönme önce dengesiz olduğunu varsayalım
  • Eğer açabilir değil ağaç dönüşten sonra dengeli farz
  • herhangi bir varsayılan G / Ç yöntemini kullanabilirsiniz
  • gönderiminiz, ağacı döndüren veya çözümü yazdıran tam program olabilir bir işlev olabilir

Test senaryoları

Bu örnekler aşağıdaki gibi bir ağacı temsil eder

  • eğer bir yapraksa: []
  • eğer anahtarlı bir xağaçsa ve her iki alt ağaç da yapraksa:[x]
  • eğer anahtar xve alt ağaçlara sahip bir ağaçsa left right:[x,left,right]

İlk örnek Rotasyonlar bölümünde verilen örnektir . Herhangi bir nedenle bunların grafiksel bir temsiline ihtiyacınız varsa, işte 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: yani herhangi bir düğüm için sol alt ağaçtaki tüm anahtarlar bu anahtardan daha küçük olacaktır ve sağ alt ağaçtaki tüm anahtarlar bundan daha büyük olacaktır

2: link-rot'ı önlemek için, onları yorum olarak yerleştirdim

Yanıtlar:


8

Haskell , 93 92 84 83 82 bayt

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

Her bir bayt için @BMO, @alephalpha ve @Laikoni ve sekiz bayt için @ nimi sayesinde!

Çevrimiçi deneyin!


Kullanmak data B=B[B]Intdaha fazla bayt tasarrufu sağlar.
Laikoni

@Laikoni sadece bir bayt sanırım ama alacağım
Angs

İlk iki vaka birleştirme, 2 bayt kurtarabilecek k<n=B[k!l,r]nve k>n=B[l,k!r]n:, içine k/=n=B[k!l,k!r]nve sonra ekleme k!x=xdesen eşleştirme ayrıntılı yapmak.
Radek

5

Vim , 25 bayt

Arabellek - boşluk ayrılmış anahtar ve ağaç girişi alır. Ağacın aşağıdaki gibi temsil edilmesi beklenmektedir:

  • Yaprak: []
  • anahtar k, sol çocuk <left>ve sağ çocuk içeren düğüm <right>:[ k <left><right>]

Anahtarın çevresindeki boşluklar könemli değil, öyle ki çözüm keyfi ağaçlar için çalışıyor.

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

Çevrimiçi deneyin!

açıklama

"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)

Ön izleme

İşte Lynn tarafından bu komut dosyası ile oluşturulan ilk test vakasının bir önizlemesi :

                       Vim önizleme


3

Wolfram Dili (Mathematica) , 30 bayt

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

Çevrimiçi deneyin!

Aşağıdaki gibi temsil edilen bir ağaç:

  • eğer bir yapraksa: $ (anahtar olmayan herhangi bir değerle değiştirebilirsiniz)
  • eğer anahtar xve alt ağaçlara sahip bir ağaçsa left right:x[left,right]

Örneğin, ilk test durumundaki ağaç şu şekilde temsil edilir: 5[3[1[$,$],4[$,$]],6[$,$]] .

Açıklama:

#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

3

Ortak Lisp, 146 bayt

(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))))))

Çevrimiçi deneyin veya tüm test kılıflarını doğrulayın!

Bir ağaç aşağıdaki gibi temsil edilir:

  • boş bir ağaç nil (boş liste olarak Common Lisp veya eşdeğer ())
  • boş olmayan bir ağaç üç öğenin bir listesi olarak temsil edilir (node left-subtree right-subtree) (bu nedenle bir yaprak Lolarak gösterilir (L nil nil)).

2

JavaScript (Node.js) , 70 bayt

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)

Çevrimiçi deneyin! Bağlantı, test senaryolarını içerir. Tüm düğümlerin sol ve sağ girişleri olmalıdır, ancak []bu tarafta alt ağaç olmadığını gösterebilirler . Bir kısaltma olarak, test takımı bir yaprak olduğunu belirtmek ve hem sol hem de hem alt hem de sağ alt ağaç olmadığını l(N)belirtmek için kullanır .Nl(N,L)NL



1

Jöle , 24 bayt

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

Çevrimiçi deneyin!

Uyarı: Normalde, üst satır mevcut olmamalı ve alt satırda a ßdeğil, a olmalıdır ç. Ancak, akıllı zincir hileleri ve ßbirlikte iyi gitmeyin,ßdeğişken değişkenlik. Teknik olarak, yine de üst çizgiyi atlamış olabilirdim, ancak daha sonra sonuç tam bir program olmalı, aksi takdirde herhangi bir programın içine kendi çizgisi olarak dahil edilebilmeliydi, şanslısın. Bu, maalesef, çıktının belirsiz bir temsili olacağı anlamına gelir, çünkü tam bir program gönderdiğinizde, aslında programın kapanmasından önce sonucun teknik olarak ne olduğunu değil, çıktıyı gerçekten alır. Bu nedenle, hem özyineleme hem de düzgün dize gösterimi ile karışıklık yapmamak için, en üst satırın işinin en altını çağırmak olduğu 2 satırlık bir işlev göndermeye karar verdim. Sonuç? 2 değerli ve değerli baytlık büyük bir atık. Jelly'in (ve Dennis'in ve diğer tüm katkıda bulunanların) savunmasında,

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.