関数型辞書のデータ構造を選択するにはどうすればよいですか?


10

次のデータ構造について少し読みました。

  • バグウェルの理想的なハッシュトライ
  • Larsonの動的ハッシュテーブル
  • 赤黒木
  • パトリシアの木

...そして他にもたくさんの人がいると思います。私はそれぞれが何に適しているのか、あるいはなぜ私が他のものを選ぶのかについてはほとんど見たことがありません。したがって、これらの行に沿っていくつかの質問があります:

  1. 知っておくべき重要な関数型辞書のデータ構造は何ですか?
  2. これらのアプローチの長所と短所は何ですか?
  3. より命令的なデータ構造を使用するのはいつ意味がありますか?

2と3の番号がより重要です。:-)


関連:岡崎以来の純粋に機能的なデータ構造の新機能 (この質問は辞書に限定されません。)
伊藤剛

この質問(3の項目以外)は、[ビッグリスト]のような感じです。
Kaveh

2
上記のリンクされた質問があなたの懸念に対処しているかどうかを知ることは役に立ちますか?
Suresh Venkat、

@Suresh-それは#1に答えますが、2と3がより重要なものでした。私は主に全体像の全体像を探しているので、どれをより深く研究する価値があるかを判断できます。
Jason

2
OK。そのため、質問を編集する価値があるかもしれません。
Suresh Venkat

回答:


16

私は迷うことなく#2に答えることはできませんが(これらの構造を比較できる次元が多すぎるため)、#3の答えは非常に簡単です。

(a)エイリアスがまったくない場合、または(b)効率的なブロードキャストのために本当にエイリアスを使用する必要がある場合は、命令型データ構造を使用します。

データ構造のエイリアスがまったくない場合、機能的なデータ構造が永続的であるという事実を利用していません。したがって、その費用を支払う理由はありません。このアドバイスには2つの注意点があります。まず、関数型データ構造の実装の単純さを好むかもしれません。関数型赤黒木に削除を実装すると呪いがかかりますが、親ポインターを使用して命令型赤黒木に削除を実装すると、自殺を熟考することになります。第2に、書き込みは若い世代からデータ構造を移動できるため、gc化された言語で期待するよりも割り当てが高くなる可能性があります。キャッシュエフェクトとGCの理論は実際にはありません。そのため、ベンチマークを行う以外に選択肢はありません。

次に、ブロードキャストチャネルが必要な場合は、共有データ構造が優れた方法です。一定時間の更新により、値が変更されたことを他の多くの人に任意に伝えることができます。(これが、union-findが非常に優れたデータ構造である理由です。)純粋に機能的なセットアップでは、他のすべての人々を変更するか、手動でコード化した状態に抽象的なポインタを与える必要があります(これは一種の鈍化です)やるべき事)。

エイリアスとオブジェクトの所有権について理由をつけたくない場合、または同じデータ構造の複数のバージョンが必要な場合(たとえば、新しいバージョンと古いバージョンの両方が必要な場合)は、関数型データ構造を使用します。

このアドバイスに従うのが一番難しいのは、グラフアルゴリズムです。非常に洗練された命令型グラフアルゴリズムはたくさんありますが、多くの場合(たとえば、コンパイラーを作成するとき)、永続性も必要になります。人々は通常、違いを分割し、クールな命令型アルゴリズムを使用しようとしますが、永続化するためにバージョン管理を側面にボルトで固定しようとします。これは一般にかなり恐ろしく、バグが多く、命令型アルゴリズムのパフォーマンス上の利点を失う傾向があります。


2
このコンテキストでエイリアスとは何ですか?
Suresh Venkat 2010

6
エイリアスは、同じデータへの複数の参照がある場合に発生します。そのデータが変更可能な場合、そのデータを使用するプログラムについての推論では、そのデータにアクセスして変更する可能性のある他のすべてのサブプログラムを明示的に考慮する必要があります。データの一部が不変である場合は、データにアクセスできるユーザーがデータを変更できないことがわかっているため、エイリアスを無視して、そのデータを使用するプログラムをローカルで推論できます。
Neel Krishnaswami 2011年

「しかし、親ポインターを使って命令型の赤黒木に削除を実装すると、自殺を熟考することになります」セジウィックの左寄りの赤黒木をチェックしてください。削除の一般的なケースは、標準のトリックによってdelete-minに削減され、delete-min自体はLLRBツリーにとって非常に簡単です。親ポインターは必要ありません。
Vognsenによる2011

1
「これは一般的にかなり恐ろしく、バグが多く、命令型アルゴリズムのパフォーマンス上の利点を失う傾向があります。」最適化コンパイラで制御フローグラフにジッパーを使用することに関するノーマンラムジーの論文は、説得力のある妥協の例を提供しています。CFGの基本ブロック間の参照の簡単で効率的なインプレース再配線をサポートするためのローカルヒープが効果的にありますが、基本ブロックのコンテンツの操作は機能的です(または、ジッパーの哲学的ビューに応じて半機能的)。
Vognsenによる2011

1

知っておくべき重要な関数型辞書のデータ構造は何ですか?

高さバランスのとれた二分木とその試行は、あらゆる点で優れた妥協策です。また:

  • パトリシアの木。
  • ハッシュトライ。

これらのアプローチの長所と短所は何ですか?

高さバランスのとれた二分木とそれらの試行は、アトミックキーの優れた妥協策です。文字列キーなど、シーケンスであるキーの場合も同じです。

パトリシアツリーは数倍速くなりますが、整数キーしか使用できません。

ハッシュの試行は、特に比較よりもハッシュが安く、ポリモーフィズムにオーバーヘッド(例:.NETの文字列)があり、ヒープへのポインターの書き込みが高速(例:JVMやCLRなどのVM)関数型言語ではなく命令型言語用に最適化されています)。ハッシュは、最適化としてミューテーションの内部使用も許可します。

赤黒木は、高さのバランスがとれた木に比べて大きなメリットはありませんが、効率的な結合、交差、差異ができないという大きな欠点があるため、それほど重要ではありません。

同様に、フィンガーツリーは実際にはあまり良くありません。

より命令的なデータ構造を使用するのはいつ意味がありますか?

ディクショナリが1度入力された後、ルックアップのみに使用されたとき、つまり凍結されたとき。

パフォーマンスが必要な場合(.NETのようなまともなハッシュテーブル Dictionaryは、一般的な純粋な関数型辞書よりも通常10〜40倍高速です)。

純粋に機能する弱い辞書が知られていないため、弱い辞書が必要な場合。

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