Rotasi pohon biner

16

Pohon pencarian biner seimbang sangat penting untuk menjamin pencarian O (log n) (atau operasi serupa). Dalam lingkungan yang dinamis di mana banyak kunci dimasukkan secara acak dan / atau dihapus, pohon mungkin berubah menjadi daftar yang ditautkan yang mengerikan untuk pencarian. Jadi ada berbagai jenis pohon biner yang dapat menyeimbangkan diri sendiri yang menetralkan efek ini (seperti pohon AVL atau pohon tebar ). Pohon-pohon ini didasarkan pada berbagai jenis rotasi yang menyeimbangkan kembali pohon.

Rotasi

Dalam tantangan ini kita hanya akan melihat rotasi kanan tunggal, rotasi seperti itu (rotasi kiri simetris) terlihat seperti ini:

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

Jika ada dedaunan 1, 4atau 6memiliki sub-pohon kiri atau kanan rotasi hanya akan membuat mereka tetap di sana. Jika ini adalah subtree dari pohon yang lebih besar, kita cukup "memotongnya" pada node 5dan "melampirkan kembali" pohon yang diputar (sekarang node 3) ke node itu.

Tantangan

Diberikan pohon pencarian biner 1 dan tombol kanan-putar pohon pada simpul itu seperti yang dijelaskan di atas. Kunci yang disediakan dalam contoh di atas adalah 5.

Aturan dan I / O

  • Anda dapat menggunakan jenis apa saja untuk kunci selama ada penipisan antara kunci pilihan Anda dan orang-orang dari kasus uji
  • Anda dapat memilih representasi untuk pohon biner selama tidak ada ambiguitas (mis. [3,[]]ambigu kecuali dinyatakan lain) dan itu wajar untuk bahasa pilihan Anda
  • karena input akan selalu menjadi pohon pencarian biner tidak ada kunci duplikat
  • Anda dapat mengasumsikan bahwa kunci tersebut terkandung dalam pohon
  • Anda dapat mengasumsikan bahwa simpul yang berisi kunci memiliki anak kiri
  • Anda mungkin tidak menganggap subtree kanan di bawah kunci yang disediakan
  • Anda mungkin tidak berasumsi bahwa pohon tidak seimbang sebelum rotasi
  • Anda mungkin tidak menganggap bahwa pohon seimbang setelah rotasi
  • Anda dapat menggunakan metode I / O standar apa pun
  • kiriman Anda mungkin merupakan fungsi mengembalikan pohon atau program lengkap mencetak solusi

Uji kasus

Contoh-contoh ini mewakili pohon sebagai berikut

  • jika daun: []
  • Jika itu pohon dengan kunci xdan kedua subtree adalah daun:[x]
  • jika itu pohon dengan kunci xdan subtree left right:[x,left,right]

Contoh pertama adalah yang disediakan di Rotasi bagian . Jika karena alasan tertentu Anda memerlukan representasi grafis dari mereka, di sini 2 Anda pergi.

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: artinya untuk setiap simpul semua kunci di subtree kiri akan lebih kecil dari kunci itu dan semua kunci di subtree kanan lebih besar dari itu

2: untuk mencegah pembusukan tautan, saya menyematkannya sebagai komentar

ბიმო
sumber

Jawaban:

8

Haskell , 93 92 84 83 82 byte

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

Terima kasih kepada @BMO, @alephalpha dan @Laikoni untuk masing-masing byte dan @nimi selama delapan byte!

Cobalah online!

Angs
sumber
Menggunakan data B=B[B]Intakan menghemat lebih banyak byte.
Laikoni
@Laikoni hanya satu byte saya pikir tapi saya akan menerimanya
Angs
Anda bisa menyimpan 2 byte dengan terlebih dahulu menggabungkan kedua case, k<n=B[k!l,r]ndan k>n=B[l,k!r]nmenjadi satu:, k/=n=B[k!l,k!r]ndan kemudian menambahkan k!x=xuntuk membuat pencocokan pola yang lengkap.
Radek
5

Vim , 25 byte

Mengambil input dalam buffer - spasi kunci dan pohon terpisah. Pohon itu diharapkan diwakili sebagai berikut:

  • daun: []
  • simpul dengan kunci k, anak kiri <left>dan anak kanan <right>:[ k <left><right>]

Bukan ruang di sekitar kunci kyang penting, sehingga solusinya bekerja untuk pohon yang sewenang-wenang.

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

Cobalah online!

Penjelasan

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

Pratinjau

Berikut ini preview dari test case pertama, yang dibuat dengan skrip ini oleh Lynn :

                       Pratinjau Vim

ბიმო
sumber
3

Bahasa Wolfram (Mathematica) , 30 byte

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

Cobalah online!

Sebuah pohon diwakili sebagai berikut:

  • jika itu adalah daun: $(Anda dapat menggantinya dengan nilai apa pun yang bukan kunci)
  • jika itu pohon dengan kunci xdan subtree left right:x[left,right]

Misalnya, pohon dalam kasus uji pertama diwakili oleh 5[3[1[$,$],4[$,$]],6[$,$]].

Penjelasan:

#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
sumber
3

Gangguan Umum, 146 byte

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

Cobalah online atau verifikasi semua testcases!

Sebuah pohon direpresentasikan sebagai berikut:

  • pohon kosong direpresentasikan sebagai nil(atau setara dalam Common Lisp sebagai daftar kosong ())
  • pohon yang tidak kosong direpresentasikan sebagai daftar tiga elemen (node left-subtree right-subtree) (sehingga daun Ldirepresentasikan sebagai (L nil nil)).
Renzo
sumber
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)

Cobalah online! Tautan termasuk kasus uji. Semua node harus memiliki entri kiri dan kanan tetapi mereka dapat []menunjukkan tidak ada subtree di sisi itu. Sebagai singkatan, test suite digunakan l(N)untuk menunjukkan bahwa itu Nadalah daun dan l(N,L)untuk menunjukkan yang Nmemiliki subtree kiri Ltetapi tidak subtree kanan baik pada input dan output.

Neil
sumber
2

Python 2 , 85 byte

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:]]

Cobalah online!

Masukkan format:

  • Pohon: [KEY, LEFT_SUBTREE, RIGHT_SUBTREE]
  • Daun: []
Erik the Outgolfer
sumber
1

Jelly , 24 byte

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

Cobalah online!

Peringatan: Biasanya, garis paling atas seharusnya tidak ada, dan garis bawah seharusnya memiliki ß, bukan a ç. Namun, trik rantai pintar dan ßtidak berjalan bersama dengan baik, karenaßvariabel arity. Secara teknis, saya masih bisa menghilangkan baris teratas, tetapi hasilnya akan menjadi program penuh, karena jika tidak maka harus dapat dimasukkan sebagai baris sendiri di dalam program apa pun, yang tidak mungkin kecuali Anda beruntung Ini berarti bahwa, sayangnya, output akan memiliki representasi yang ambigu, karena, ketika Anda mengirimkan program lengkap, apa yang benar-benar menghasilkan jumlah output, dan bukan apa hasilnya secara teknis sebelum program ditutup. Jadi, agar tidak membuat kekacauan dengan rekursi dan representasi string yang tepat, saya telah memutuskan untuk menyerahkan fungsi 2-baris, di mana pekerjaan baris atas adalah memanggil yang bawah. Konsekuensinya? Buang besar 2 byte berharga dan berharga. Dalam pertahanan Jelly (dan Dennis, serta setiap kontributor lainnya),

Erik the Outgolfer
sumber