web-dev-qa-db-ja.com

二分探索対二分木

二分探索によるソートされた配列に対する二分探索木の利点は何ですか?数学的分析だけでは違いは見られないので、低レベルの実装オーバーヘッドには違いがあるはずだと思います。平均ケース実行時間の分析を以下に示します。

二分探索によるソートされた配列
検索:O(log(n))
挿入:O(log(n))(要素を挿入する場所を見つけるためにバイナリ検索を実行します)
削除:O(log(n))(削除する要素を見つけるためにバイナリ検索を実行します)

二分探索木
検索:O(log(n))
挿入:O(log(n))
削除:O(log(n))

二分探索木は、上記の操作で最悪の場合O(n))であるため(木がバランスされていない場合)、これは実際には二分探索でソートされた配列よりも悪いようです。

また、事前に配列を並べ替える必要があるとは想定していません(O(nlog(n)のコストがかかります)。バイナリツリーの場合と同じように、要素を1つずつ配列に挿入します。唯一の利点私が見ることができるBSTのそれは、順序付け、事前注文、事後注文のような他のタイプのトラバーサルをサポートしているということです。

27
john

分析が間違っています。挿入と削除の両方がO(n)ソートされた配列の場合、挿入用のスペースを作成するためにデータを物理的に移動する必要があるためです。削除されたアイテムを隠すためにそれを圧縮します。

ああ、完全に不均衡な二分探索木の最悪のケースは、O(logn)ではなくO(n)です。

29
Blindy

queryingのどちらにもあまりメリットはありません。

ただし、要素を1つずつ追加する場合、ソートされたツリーの構築は、ソートされた配列の構築よりもはるかに高速です。したがって、完了したら配列に変換しても意味がありません。

7
Mehrdad

バランスの取れた二分探索木を維持するための標準的なアルゴリズムがあることにも注意してください。彼らは二分木の欠陥を取り除き、他のすべての強みを維持します。ただし、これらは複雑なので、最初に二分木について学ぶ必要があります。

それを超えて、big-Oは同じかもしれませんが、定数は常にではありません。二分木では、データを正しく保存すれば、複数のレベルでキャッシュを非常に有効に活用できます。その結果、多くのクエリを実行している場合、ほとんどの作業はCPUキャッシュ内にとどまり、処理が大幅に高速化されます。これは、ツリーの構造に注意を払う場合に特に当てはまります。ツリーの巧妙なレイアウトの例については、 http://blogs.msdn.com/b/devdev/archive/2007/06/12/cache-oblivious-data-structures.aspx を参照してください。パフォーマンスが大幅に向上します。バイナリ検索を行う配列では、そのようなトリックを使用することはできません。

2
btilly