私はHaskellを学び、演習としてバイナリツリーを作成しています。通常の二分木を作成したので、それを自己均衡化に適応させたいと思います。そう:
- どちらが最も効率的ですか?
- どちらが最も簡単に実装できますか?
- 最もよく使用されるのはどれですか?
しかし、決定的に、どちらをお勧めしますか?
これは議論の余地があるため、ここに属していると思います。
私はHaskellを学び、演習としてバイナリツリーを作成しています。通常の二分木を作成したので、それを自己均衡化に適応させたいと思います。そう:
しかし、決定的に、どちらをお勧めしますか?
これは議論の余地があるため、ここに属していると思います。
回答:
私はあなたがいずれかで始まる推薦する赤黒木、またはAVL木。
赤黒ツリーは挿入が高速ですが、AVLツリーには検索用のわずかなエッジがあります。AVLツリーの実装はおそらく少し簡単ですが、私自身の経験に基づいたものではありません。
AVLツリーは、挿入または削除のたびにツリーのバランスを取ります(1 / -1より大きいバランス係数を持つサブツリーはありませんが、赤黒ツリーは、ツリーがいつでも合理的にバランスを取ることを保証します。
ランダム化されたデータ構造に問題がない場合は、別の方法を検討します:Skip Lists。
高レベルの観点から見ると、ツリー構造ですが、ツリーとしてではなく、複数のリンク層を持つリストとして実装されています。
O(log N)の挿入/検索/削除を取得し、これらのトリッキーなリバランスのケースすべてに対処する必要はありません。
私はそれらを関数型言語で実装することを考えたことはありません、そしてウィキペディアのページには何も表示されないので、それは簡単ではないかもしれません
比較的簡単な構造(AVLツリーと赤黒ツリーの両方が厄介です)から始める場合、1つのオプションは「ツリー」と「ヒープ」の組み合わせとして名前が付けられたトレープです。
各ノードは「優先度」の値を取得します。多くの場合、ノードの作成時にランダムに割り当てられます。ノードは、キーの順序が尊重されるように、また優先順位値のヒープのような順序が尊重されるように、ツリーに配置されます。ヒープのような順序とは、親の両方の子が親よりも優先順位が低いことを意味します。
EDITは 上記の「キー値内」を削除しました-優先順位とキーの順序は一緒に適用されるため、一意のキーであっても優先順位は重要です。
面白い組み合わせです。キーが一意であり、優先度が一意である場合、ノードのセットには一意のツリー構造があります。それでも、挿入と削除は効率的です。厳密に言えば、ツリーは事実上リンクリストになるまで不均衡になる可能性がありますが、これは(標準バイナリツリーとは異なり)キーが順番に挿入されるなどの通常の場合を含め(標準バイナリツリーとは異なり)非常にまれです。
どちらが最も効率的ですか?
あいまいで答えるのが難しい。計算の複雑さはすべて明確に定義されています。それが効率という意味であれば、本当の議論はありません。実際、すべての優れたアルゴリズムには、証明と複雑さの要因が付属しています。
「ランタイム」または「メモリ使用」を意味する場合、実際の実装を比較する必要があります。次に、言語、ランタイム、OS、およびその他の要因が作用し、質問への回答が難しくなります。
どちらが最も簡単に実装できますか?
あいまいで答えるのが難しい。一部のアルゴリズムは複雑に見えるかもしれませんが、私には些細なことです。
最もよく使用されるのはどれですか?
あいまいで答えるのが難しい。最初に「誰によって」があります これの一部?Haskellのみ?CまたはC ++はどうですか?第二に、調査を行うためにソースにアクセスできない独自のソフトウェアの問題があります。
しかし、決定的に、どちらをお勧めしますか?
これは議論の余地があるため、ここに属していると思います。
正しい。あなたの他の基準はあまり役に立たないので、これがあなたが得ようとしているすべてです。
多数のツリーアルゴリズムのソースを取得できます。何かを学びたい場合は、見つけることができるものをすべて実装するだけです。「推奨」を求めるのではなく、見つけることができるすべてのアルゴリズムを収集してください。
リストは次のとおりです。
http://en.wikipedia.org/wiki/Self-balancing_binary_search_tree
6つの一般的な定義があります。それらから始めます。
スプレイツリーに興味がある場合は、アレンとマンローの論文で最初に説明されたと思われるものよりも簡単なバージョンがあります。同じパフォーマンスの保証はありませんが、「zig-zig」と「zig-zag」のリバランスを処理する際の複雑さを回避します。
基本的に、検索時(削除する挿入ポイントまたはノードの検索を含む)、検索したノードは、ルートに向かって、ボトムアップで直接回転します(たとえば、再帰的検索関数が終了するとき)。各ステップで、ルートに向かって別のステップをプルアップする子が右の子であるか左の子であるかに応じて、単一の左または右の回転を選択します(回転方向を正しく覚えていれば、それぞれです)。
Splayツリーのように、最近アクセスしたアイテムは常にツリーのルートの近くにあるため、すぐに再びアクセスできるという考え方です。これらのAllen-Munroeのroot-to-rootツリー(私がそれらを呼ぶもの-正式名称は知らない)はより簡単になりますが、同じ償却パフォーマンス保証はありません。
一つのこと-このデータ構造は定義上、検索操作に対しても変化するため、おそらく一元的に実装する必要があります。IOWは、関数型プログラミングには向いていないかもしれません。