web-dev-qa-db-ja.com

BSTのバランス

参考:この質問は、@ MS SDEインタビュー、3回目です。そして、それは宿題の問題ではありません。また、私はそれを考えて、以下で私のアプローチに言及しました。

質問:BSTを修正して、可能な限りバランスが取れるようにします。言うまでもなく、できるだけ効率的に行う必要があります。

ヒント:インタビュアーは、これが論理的な質問だと言いました。違った考え方をすれば答えが得られます。難しいコーディングは必要ありません。
->そうは言っても、彼は私がAVL/RB Treesを指すと期待していたとは思わない。

私の解決策:私は、ツリーの順序走査を行い、中間要素を新しいツリーのルートとして取得することを提案しました(新しいルートと呼びます)。次に、中間要素の左側の部分に移動し、その中間要素を新しいルートのツリーの左サブツリーのルートとして取得します。同様に、右側の部分についても同様です。これを再帰的に行うと、最適なバランスの取れたBSTが得られます。

私がここに投稿している理由:しかし、彼は答えに満足していませんでした:(だから、本当にこれを行う方法がないのですか? weights/RBカラーリング戦略、それとも彼はただ私にだまされていましたか?あなたの専門家の考えを入れてください。

Duplicate?いいえ!私はこれがあることを知っています 質問 しかし、リクエスタによって提案された解決策はあまりにも複雑であり、他の人はAVLツリーについて話します。

41
ADJ

Day-Stout-Warrenアルゴリズム(O(n)-time、O (1)任意の二分探索木を完全な二分木に再形成するための空間アルゴリズム。直感的に、アルゴリズムは次のように機能します。

  1. ツリーの回転を使用して、ツリーを縮退リンクリストに変換します。
  2. リンクリストに選択ローテーションを適用することにより、リストを完全にバランスの取れたツリーに変換します。

このアルゴリズムの利点は、線形時間で実行され、一定のメモリオーバーヘッドのみを必要とすることです。実際、新しいツリーを作成して古いデータをコピーするのではなく、基礎となるツリーを再形成するだけです。コーディングも比較的簡単です。

お役に立てれば!

39
templatetypedef

「可能な限りバランス」= 完全な(または完全な)二分木1。それ以上にバランスを取ることはできません。

解決策は簡単です。「空の」完全な二分木を構築し、新しい木と入力木を(同時に)順番に走査して完全な木を埋めます。

完了すると、最もバランスの取れたツリーを取得できます。このアプローチの時間の複雑さはO(n)です。


編集:
次の手順に従ってください。

  1. nノードでダミーの完全なツリーを構築します。各ノードへのすべての値は、何らかのゴミ値に初期化されます。
  2. 2つのイテレータを作成します。(1)元のツリーのoriginalIter、(2)新しい(ガベージで初期化された)ツリーのnewIter。両方のイテレータは、順序通りに要素を返します。
  3. 次を実行して、元の値をツリーに入力します。

     while (originalIter.hasNext()):
          newIter.next().value = originalIter.next().value
    

(1)(Wikipediaより):完全な二分木とは、最後のレベルを除くすべてのレベルが完全に満たされ、すべてのノードが可能な限り残っている二分木です。

15
amit

DSWアルゴリズムはこれを解決できますO(n)時間。アルゴリズムは次のようになります。

1] Using right-rotation operations, turn the tree into a linked list
   (a.k.a. backbone or Vine)
2] Rotate every second node of the backbone about its parent to turn
   the backbone into a perfectly balanced BST. 

参照

11
thunderbird