これら2つのデータ構造の主な違いは何か説明していただけますか?私は、違い/類似点を強調するソースをオンラインで見つけようとしましたが、あまり有益なものは見つかりませんでした。どのような場合に一方が他方よりも優先されますか?一方が他方よりも「使いやすい」ようにする実用的な状況は何ですか?
AVLツリーは、赤黒ツリーよりも厳密なバランスを維持します。 AVLツリーのルートから最も深い葉までのパスは最大で1.44 lg(n + 2)ですが、赤黒のツリーでは最大で2 lg(n + 1)です。
その結果、AVLツリーでのルックアップは通常より高速になりますが、ローテーション操作が増えるため、挿入と削除が遅くなります。したがって、ルックアップの数がツリーの更新の数よりも多いと予想される場合は、AVLツリーを使用してください。
小さなデータの場合:
挿入:RBツリーとavlツリーの最大回転数は一定ですが、平均してRBツリーの回転数が少ないため、RBツリーは高速になります。
lookup:AVLツリーの深さが小さいため、AVLツリーの方が高速です。
削除:RBツリーの最大回転数は一定ですが、AVLツリーではO(log N)回の回転が最悪の場合があります。また、平均してRBツリーの回転数も少ないため、RBツリーの方が高速です。
大きなデータの場合:
挿入:AVLツリーの方が高速です。挿入する前に特定のノードを検索する必要があるためです。データが増えると、特定のノードのルックアップの時間差がO(log N)に比例して大きくなります。しかし、AVLツリーとRBツリーでは、最悪の場合でも一定の回転数しか必要ありません。したがって、ボトルネックは、その特定のノードを検索する時間になります。
lookup:AVLツリーは高速です。 (小さなデータの場合と同じ)
削除:AVLツリーは平均して高速ですが、最悪の場合、RBツリーは高速です。削除する前にスワップする非常に深いノードも検索する必要があるためです(挿入の理由と同様)。平均して、両方のツリーの回転数は一定です。ただし、RBツリーには回転の上限が一定です。
これから引用: AVLツリーと赤黒ツリーの違い
RBツリーは、AVLツリーと同様に、自己分散型です。どちらもO(log n)ルックアップと挿入のパフォーマンスを提供します。違いは、RBツリーが挿入操作ごとにO(1)ローテーションを保証することです。これが実際の実装で実際にパフォーマンスを犠牲にしているものです。動的なノード構造のオーバーヘッドを持ち越さないツリー物理的にRB-Treeはバイナリツリーとして実装され、赤/黒フラグは2-3の動作をシミュレートします。
したがって、定義により、すべてのAVLは赤黒のサブセットです。再構築や回転を行わずに任意のAVLツリーを色付けして、赤黒ツリーに変換できる必要があります。
AVLツリーは、多くの場合、赤黒ツリーと比較されます。これは、両方が同じ操作セットをサポートし、基本操作に
O(log n)
時間かかるためです。ルックアップを多用するアプリケーションの場合、AVLツリーはより厳密にバランスが取れているため、赤黒ツリーよりも高速です。赤黒木と同様に、AVL木は高さのバランスが取れています。一般に、両方とも、μ≤½の場合、重量バランスもμバランスもありません。つまり、兄弟ノードは非常に異なる数の子孫を持つことができます。
AVL Trees のウィキペディアの記事から
木の最大の高さは、バランスを保つために重要です。 AVLでは1.44 * log(n)
とほぼ同じですが、RBツリーでは2 * log(n)
です。したがって、問題が検索インセンティブである場合、AVLを使用する方が良いという結論を得ることができます。重要なのは、AVLおよびRBツリーに関する別の質問です。 RBツリーは、ローテーションの低コストでランダム挿入に直面する場合、AVLよりも優れていますが、AVLは昇順または降順のデータを挿入するのに適しています。したがって、問題が挿入インセンティブの場合、RBツリーを使用できます。
ただし、RedBlackツリーの回転が少ないという事実により、挿入/削除時の回転が速くなる可能性があります。通常は少し深いので、挿入と削除の速度が遅くなることもあります。ツリーのあるレベルから次のレベルに進むたびに、要求された情報がキャッシュになく、RAMから取得する必要があるという大きな変更があります。したがって、より深くナビゲートする必要があるため、キャッシュをより頻繁に更新する必要があるため、少ない回転で得られた時間がすでに失われている可能性があります。キャッシュから操作できるかどうかが大きな違いになります。関連情報がキャッシュにある場合、追加のレベルをナビゲートするのに必要な時間内に複数のローテーション操作を実行でき、次のレベルの情報はキャッシュにありません。したがって、RedBlackが理論的には高速で、必要な操作だけを見る場合、キャッシュミスのために実際には遅くなる可能性があります。
AVLツリーの仕組みを理解するには、 this インタラクティブな視覚化が役立ちます。
AVLおよびRedBlack Treeは、高さのバランスが取れたツリーデータ構造です。それらは非常に似ており、実際の違いは、追加/削除操作で行われる回転操作の数にあります。AVLの場合は、より均一なバランスを維持するために高くなります。
両方の実装はO(lg N)
(Nはリーフの数)としてスケーリングしますが、実際には検索集中タスクでAVLツリーの方が高速です。より良いバランスを利用して、ツリートラバーサルは平均で短くなります。一方、挿入と削除の点では、AVLツリーの方が遅くなります。変更時にデータ構造を適切に再調整するには、より多くのローテーションが必要です。
汎用の実装(つまり、ルックアップが操作の大部分であるかどうかは事前にはわかりません)には、RedBlack Treesが推奨されます。それらは実装が簡単で、一般的なケースでは高速です-データ構造が検索されるたびに変更される場所。例:TreeMap
およびTreeSet
in Java補助的なRedBlack Treeを使用します。
要約すると、AvlTreesはRedBlackTreesよりもわずかに優れたバランスです。両方のツリーは、ルックアップ、挿入、削除に全体でO(log n)時間かかりますが、挿入と削除には前者はO(log n)回転を必要としますが、後者はO(1) =回転。
回転はメモリへの書き込みを意味し、メモリへの書き込みは高価なため、RedBlackTreesは実際にはAvlTreesよりも更新が高速です。
私が見てきたことから、AVLツリーは、AVLツリー(Log n)の望ましい高さを得るために必要なだけの回転(再帰的にツリーを上に上げる)を行うようです。これにより、バランスがより厳密になります。
レッドブラックツリーの場合、挿入と削除を確実に行うために必要な5つのルールセットがあります。これは、ここで見つけることができます http://en.wikipedia.org/wiki/Red-black_tree 。
赤黒木に役立つ主なことは、これらの5つのルールに応じて、叔父が赤の場合にルートまでツリーを再帰的に色付けできるという事実です。おじさんが黒人なら、問題を修正するために最大2回転する必要がありますが、1回転か2回転した後は完了です。それを詰め込んでおやすみなさい。それがあなたがする必要のある操作の終わりだからです。
ビッグルールは5番です...「指定されたノードからその子孫の葉へのすべての単純なパスには、同じ数の黒いノードが含まれています」。
これにより、ツリーを機能させるために必要なほとんどの回転が発生し、ツリーのバランスが崩れすぎません。