バイナリツリーの回転


16

バランスの取れたバイナリ検索ツリーは、O(log n)ルックアップ(または同様の操作)を保証するために不可欠です。多数のキーがランダムに挿入および/または削除される動的環境では、ツリーがルックアップにとって恐ろしいリンクリストに縮退する場合があります。したがって、この効果に対抗するさまざまな種類の自己バランス型バイナリツリーAVLツリースプレイツリーなど)があります。これらのツリーは、ツリーのバランスを再調整するさまざまな種類の回転に基づいています。

回転

この課題では、単一の右回転のみを見ていきます。そのような回転(左回転は対称)は次のようになります。

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

葉のいずれか14または6左または右のサブツリーがある場合、回転は単にそれらをそこに保持します。これがより大きなツリーのサブツリーである場合、ノードで単に「切断5」し、回転したツリー(現在のノード3)をそのノードに「再接続」します。

チャレンジ

バイナリ検索ツリー1とキーを指定すると、上記のようにそのノードでツリーが右回転します。上記の例で提供されるキーはになります5

ルールとI / O

  • 選択したキーとテストケースのキーの間に全単射がある限り、任意のタイプのキーを使用できます。
  • [3,[]]あいまいさがなければ(たとえば、特に指定しない限りあいまいです)、選択した言語に自然な限り、バイナリツリーの表現を選択できます。
  • 入力は常にバイナリ検索ツリーになるため、重複キーはありません
  • あなたはキーがツリーに含まれていると仮定するかもしれません
  • キーを含むノードには左の子があると仮定できます
  • 提供されたキーの下に正しいサブツリーを想定することはできません
  • あなたは、回転の前にツリーがアンバランスであると仮定することはできません
  • 回転後にツリーのバランスが取れていると思わないかもしれません
  • デフォルトのI / O方式を使用できます
  • あなたの提出は、ツリーを返す関数またはソリューションを印刷する完全なプログラムである可能性があります

テストケース

これらの例は、次のようなツリーを表します

  • 葉の場合: []
  • キーxを持つツリーで、両方のサブツリーがリーフの場合:[x]
  • キーxとサブツリーを持つツリーの場合left right[x,left,right]

最初の例は、セクションRotationsで提供されるものです。何らかの理由でそれらをグラフィカルに表示する必要がある場合は、ここで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:つまり、任意のノードで、左側のサブツリーのすべてのキーがそのキーよりも小さく、右側のサブツリーのすべてのキーがそれよりも大きいことを意味します

2:リンク腐敗を防ぐため、コメントとして埋め込みました

回答:


8

Haskell93 92 84 83 82バイト

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

@ BMO、@ alephalpha、@ Laikoniがそれぞれ1バイト、@ nimiが8バイトに感謝します!

オンラインでお試しください!


を使用data B=B[B]Intすると、さらにバイトが節約されます。
ライコニ

@Laikoniちょうど1バイトと思うが、私はそれを取るだろう
-Angs

あなたは最初の2例をマージする、ことにより、2つのバイトを救うことができるk<n=B[k!l,r]nk>n=B[l,k!r]n:、一つにk/=n=B[k!l,k!r]nして、追加k!x=xのパターンマッチング網羅を作ること。
ラデク

5

Vim、25バイト

バッファ内の入力を受け取ります-スペースで区切られたキーとツリー。ツリーは次のように表されることが期待されています。

  • 葉: []
  • キーk、左の子<left>、および右の子を持つノード<right>[ k <left><right>]

キーの周りのk重要なスペースではなく、ソリューションが任意のツリーで機能するようにします。

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

オンラインでお試しください!

説明

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

プレビュー

Lynnこのスクリプトで生成した最初のテストケースのプレビューを次に示します。

                       Vimプレビュー


3

Wolfram言語(Mathematica)、30バイト

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

オンラインでお試しください!

次のように表されるツリー:

  • リーフの場合:($キーではない任意の値に置き換えることができます)
  • キーxとサブツリーを持つツリーの場合left rightx[left,right]

たとえば、最初のテストケースのツリーはで表され5[3[1[$,$],4[$,$]],6[$,$]]ます。

説明:

#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

Common Lisp、146バイト

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

オンラインそれを試してみたり、すべてのテストケースを検証!

ツリーは次のように表されます。

  • 空のツリーは、次のように表されるnil(空のリストなどの一般的なLispでまたは同等()
  • 空でないツリーは3つの要素のリストとして表されます(node left-subtree right-subtree) (したがって、葉Lはとして表されます(L nil nil))。

2

JavaScript(Node.js)、70バイト

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)

オンラインでお試しください!リンクにはテストケースが含まれます。すべてのノードには左右のエントリが必要ですが[]、その側にサブツリーがないことを示している可能性があります。略語として、テストスイートl(N)はそれNがリーフであるl(N,L)ことを示し、入力と出力の両方にN左サブツリーLがあるが右サブツリーがないことを示すために使用します。



1

ゼリー、24バイト

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

オンラインでお試しください!

警告:通常、一番上の行は存在してはならず、一番下の行にはa ßではなくaが必要çです。ただし、巧妙なチェーントリックßはうまくいかないため、うまくいかないßの可変アリティ。技術的には、一番上の行をまだ省略できますが、結果は完全なプログラムである必要があります。そうでない場合は、プログラム内に独自の行として組み込むことができる必要があるため、ラッキーだ。これは、残念なことに、完全なプログラムを送信すると、実際に出力カウントを取得するものであり、プログラムが閉じる前に結果が技術的に何であるかではなく、出力があいまいな表現になったことを意味します。したがって、再帰と適切な文字列表現の両方で混乱しないように、2行の関数を送信することにしました。結果は?2つの貴重で貴重なバイトの巨大な無駄。ゼリー(およびデニス、および他のすべての貢献者)の防衛において、

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.