web-dev-qa-db-ja.com

あまり知られていないが有用なデータ構造は何ですか?

その周りには本当に便利なデータ構造がいくつかありますが、ほとんどのプログラマーには知られていません。それらはどれですか?

誰もがリンクリスト、バイナリツリー、ハッシュについて知っていますが、 リストをスキップする そして ブルームフィルタについては 例えば。あまり一般的ではないデータ構造をもっと知りたいのですが、素晴らしいアイデアに頼り、プログラマのツールボックスを充実させるので、知っておく価値があります。

追伸:私は ダンスのリンク のようなテクニックにも興味を持っています - /それは共通のデータ構造のプロパティを巧みに利用します。

_ edit _ :もっと詳しくデータ構造を記述しているページにリンクを含むをしてみてください。また、why​​ _の上にいくつかの単語を追加してみてください( JonasKölker はすでに指摘したように)。また、回答ごとに1つのデータ構造を指定してみてください。これは彼らの投票だけに基づいてより良いデータ構造がトップに浮かぶことを可能にするでしょう。

796
f3lix

トライ は、prefix-treesまたは crit-bitツリーとしても知られています は、40年以上前から存在していましたが、まだ比較的未知のものです。トライの非常にクールな使い方は、トライとハッシュ関数を組み合わせた「 TRASH - 動的なLCトライとハッシュデータ構造 」で説明されています。

271
David Phillips

ブルームフィルタ m ビットのビット配列。最初はすべて0に設定されています。

項目を追加するには、 k ハッシュ関数を使用して実行し、配列内の k インデックスを取得してから1に設定します。

項目がセット内にあるかどうかを調べるには、 k インデックスを計算し、それらがすべて1に設定されているかどうかをチェックします。

もちろん、これは誤検知の可能性をある程度もたらします(ウィキペディアによると、約0.61 ^(m/n)で、nは挿入されたアイテムの数です)。偽陰性は不可能です。

アイテムを削除することは不可能ですが、整数の配列とインクリメント/デクリメントで表される ブルームフィルタをカウントする を実装することができます。

231
lacop

Rope :安価な先頭、部分文字列、中間挿入、追加を可能にする文字列です。私は本当に一度だけそれを使ったことがありましたが、他の構造では十分ではなかったでしょう。通常の文字列と配列の先頭に追加することは、私たちがする必要があることのためには非常に高価すぎました、そして反転を逆にすることは問題外でした。

140
Patrick

スキップリスト はかなりきれいです。

ウィキペディア
スキップリストは、二分探索木に匹敵する効率を有する、多数の並列のソートされたリンクリストに基づく確率的データ構造である(大部分の操作について平均対数平均時間)。

それらはバランスのとれたツリーに代わるものとして使用することができます(バランスの厳密な実施よりもむしろ確率的バランスを使用して)。それらは実装が簡単で、言うよりも速く、赤黒の木です。私は彼らがすべての良いプログラマーのツールチェストにあるべきだと思います。

スキップリストの詳細な紹介が欲しいなら、ここに ビデオへのリンク /それらに関するMITのIntroduction to Algorithms講義の/があります。

また、 here はスキップリストを視覚的に示すJavaアプレットです。

128
mmcdole

空間インデックス 、特に Rツリー および KDツリー は、空間データを効率的に格納します。これらは、地理的な地図座標データやVLSIの配置配線アルゴリズム、そして最近傍検索に適しています。

ビット配列 個々のビットをコンパクトに格納し、高速のビット操作を可能にします。

92
Yuval F

ジッパー - 'カーソル'の現在の位置の自然な概念を持つように構造を変更するデータ構造の派生物。これらは証印が範囲外にならないことを保証するので本当に便利です。 xmonadウィンドウマネージャ どのウィンドウがフォーカスされているかを追跡します。

驚くべきことに、あなたは 計算からのテクニックを 元のデータ構造の型に適用することによって - それらを派生させることができます!

87
Don Stewart

ここにいくつかあります:

  • サフィックスが試みます。ほとんどすべての種類の文字列検索に役立ちます( http://en.wikipedia.org/wiki/Suffix_trie#Functionality )。接尾辞配列も参照してください。接尾辞の木ほど速くはありませんが、ずっと小さいです。

  • (上記のように)木を広げます。それらがクールな理由は3つあります。

    • それらは小さいです:あなたはどんな二分木でもそうするようにあなたは左右のポインタだけを必要とします(ノードカラーまたはサイズ情報を格納する必要はありません)
    • それらは(比較的)実装が非常に簡単です。
    • 彼らは全体のホストのための最適な償却された複雑さを提供します「測定基準」(log nルックアップ時間は誰もが知っているものです)。 http://en.wikipedia.org/wiki/Splay_tree#Performance_theorems を参照してください。
  • ヒープ順検索ツリー:キーに関して検索ツリーになり、優先度に関してヒープ順になるように、(key、prio)ペアの束をツリーに格納します。そのような木は独特の形をしていることを示すことができます(そしてそれは常に完全に左に詰め込まれているわけではありません)。ランダムな優先順位で、それはあなたに期待されるO(log n)検索時間、IIRCを与えます。

  • ニッチなものは、O(1)隣接クエリを持つ無向平面グラフの隣接リストです。これは、既存のデータ構造を編成するための特定の方法ほどのデータ構造ではありません。これを行う方法は次のとおりです。すべての平面グラフは最大6の次数を持つノードを持ちます。そのようなノードを選び、その隣人を隣人リストに入れ、それをグラフから取り除き、そしてグラフが空になるまで繰り返します。ペア(u、v)が与えられたら、vの隣接リストの中のuと、uの隣接リストの中のvを探します。両方とも最大で6のサイズを持つので、これはO(1)です。

上記のアルゴリズムにより、もしuとvが隣人なら、あなたはvのリストにvとuのリストにvの両方を持つことはないでしょう。これが必要な場合は、各ノードの欠けている隣人をそのノードの隣人リストに追加するだけですが、高速検索のために調べる必要がある隣人リストの量を保存します。

69
Jonas Kölker

私は、標準的なデータ構造に代わるロックフリーなもの、すなわちロックフリーのキュー、スタック、リストは見過ごされがちです。
同時読み取り/書き込みを処理するためにMutexまたはロックを使用するよりも、同時実行性が優先され、賞賛に値する目標になるにつれて、これらの関連性が高まります。

ここにいくつかのリンクがあります
http://www.cl.cam.ac.uk/research/srg/netos/lock-free/
http://www.research.ibm.com/people/m/michael/podc-1996.pdf [PDFへのリンク]
http://www.boyet.com/Articles/LockfreeStack.html

Mike Actonの (挑発的なことが多い)ブログには、ロックのない設計とアプローチに関する優れた記事がいくつかあります。

65
zebrabox

Disjoint Set たくさんのアイテムを個別のセットに分割してメンバーシップを照会する必要がある場合には、かなり気の利いた方法だと思います。 UnionおよびFind操作を正しく実装すると、実質的に一定の償却コストが発生します(データ構造クラスを正しく思い出した場合、Ackermnanの関数の逆関数)。

55
Dana

フィボナッチヒープ

これらは最短経路問題などのグラフ関連の問題の多くに対して(漸近的に)知られている最速のアルゴリズムのいくつかで使用されています。 Dijkstraのアルゴリズムは標準的なバイナリヒープでO(E log V)時間で実行されます。フィボナッチヒープを使用すると、O(E + V log V)に改善されます。これは、密グラフの場合は非常に高速です。しかし残念なことに、それらは高い定数係数を持っているので、実際には実用的ではないことがよくあります。

52
Adam Rosenfield

3Dレンダリングの経験がある人なら誰でも BSPツリー になじみがあるはずです。一般的には、カメラの座標と方位を知っているため、レンダリングを管理しやすいように3Dシーンを構成する方法です。

二値空間分割(BSP)は、超平面によって再帰的に空間を凸集合に細分割するための方法である。この細分化は、BSPツリーとして知られるツリーデータ構造によるシーンの表現を生じさせる。

言い換えれば、それは複雑な形状の多角形を凸集合、または完全に非反射角(180°より小さい角度)からなるより小さい多角形に分割する方法である。スペース分割のより一般的な説明については、スペース分割を参照してください。

元来、このアプローチはレンダリング効率を高めるために3Dコンピュータグラフィックスで提案されました。他の用途としては、CADにおける形状(構成的立体形状)を用いた幾何学的操作、ロボット工学および3Dコンピュータゲームにおける衝突検出、および複雑な空間シーンの処理を含む他のコンピュータ用途が挙げられる。

44
spoulson

ハフマン木 - 圧縮に使われる。

43
Lurker Indeed

Finger Trees を見てください。特に 前述 純粋に機能的なデータ構造のファンであれば。これらは、償却された一定時間での終わりへのアクセス、および小さい断片のサイズでの時間対数での連結および分割をサポートする永続シーケンスの機能的表現です。

元の記事 に従って:

私たちの2〜3本のフィンガーツリーは、Okasaki(1998)によって導入された 暗黙的再帰的スローダウン と呼ばれる一般的な設計手法の一例です。これらのツリーは、暗黙の両端キュー構造を拡張したものであり、効率的な連結と分割に必要な柔軟性を提供するために、ペアを2〜3ノードに置き換えたものです。

Finger Treeは monoid でパラメータ化することができ、異なるモノイドを使用するとツリーの動作が異なります。これにより、Finger Treesは他のデータ構造をシミュレートできます。

38
huitseeker

循環バッファまたはリングバッファ - とりわけストリーミングに使用されます。

34
cdonner

私は誰もMerkleの木について言及していないことに驚いています(つまり Hash Trees )。

利用可能なファイルの一部しかない場合にファイル全体のハッシュを検証したい多くの場合(P2Pプログラム、デジタル署名)に使用されます。

<zvrba> Van Emde-Boasの木

なぜ かっこいいです。一般に、「なぜ」という質問が最も重要な質問です。

私の答えは、使用中のキーの数に関係なく、{1..n}キーを持つO(log log n)個の辞書を提供することです。繰り返し半分にするとO(log n)が得られるのと同じように、sqrtingを繰り返すとO(log log n)が得られます。これがvEBツリーで発生します。

32
Jonas Kölker

スプレー木はどうですか

また、Chris Okasakiの 純粋に機能的なデータ構造 が頭に浮かぶ。

31
starblue

ハッシュテーブルの興味深い変種は Cuckoo Hashing です。ハッシュ衝突を処理するために、1つではなく複数のハッシュ関数を使用します。衝突は、プライマリハッシュで指定された場所から古いオブジェクトを削除し、それを代替ハッシュ関数で指定された場所に移動することによって解決されます。 Cuckoo Hashingでは、3つのハッシュ関数で負荷率を最大91%まで上げることができ、しかもアクセス時間が良好なため、メモリスペースをより効率的に使用できます。

29
A. Levy

min-max heapheap の変形であり、両端優先度キューを実装しています。これは、ヒーププロパティを単純に変更することで実現されます。偶数(奇数)レベルのすべての要素がすべての子供や孫よりも小さい(大きい)場合、ツリーは最小 - 最大順に並べられます。レベルは1から始まります。

http://internet512.chonbuk.ac.kr/datastructure/heap/img/heap8.jpg

27
marcog

キャッシュ忘却データ構造が好きです 。基本的な考え方は、たくさんの異なるサイズのキャッシュがそれらに都合の良いブロックを利用できるように、再帰的に小さなブロックでツリーをレイアウトすることです。これにより、RAMのL1キャッシュからディスクから読み取られる大量のデータまで、これらのキャッシュレイヤのサイズの詳細を知らなくても、キャッシュを効率的に使用できます。

26
btilly

左に傾いている赤黒の木 。 Robert Sedgewickによる、赤黒木の実装を大幅に簡略化したものが2008年に公開されました(実装するコードの半分までの行)。 Red-Blackツリーの実装に頭を包むのに苦労したことがあるなら、この変種について読んでください。

Andersson Treesと非常によく似ています(同一ではない場合)。

23
Lucas

作業盗用キュー

作業を複数のスレッドに均等に分割するためのロックフリーのデータ構造 C/C++での作業スチールキューの実装

22
Marko Tintor

ブートストラップされた2項ヒープ GerthStøltingBrodalとChris Okasakiによる:

それらの長い名前にもかかわらず、それらは関数設定においてさえも漸近的に最適なヒープ操作を提供します。

  • O(1)のサイズ、 共用体 、挿入、最小
  • O(log n) deleteMin

leftist heaps のように、データ構造の教科書で一般的に扱われている一般的なヒープとは異なり、unionはO(1)時間ではなくO(log n)時間がかかることに注意してください。そして フィボナッチヒープとは異なり 、これらの漸近式は、たとえ永続的に使われたとしても、償却されるのではなく最悪のケースです。

Haskellには 複数の実装 があります。

Brodalが 命令ヒープ と同じ漸近式を考え出した後、それらはBrodalとOkasakiによって共同で導出されました。

19
Edward KMETT
  • Kd-Trees (リアルタイムレイトレーシングで使用されているものの中でも特に使用される)空間データ構造では、異なるスペースと交差する三角形を切り取る必要があるという欠点があります。一般的にBVHはより軽量なので高速です。
  • MX-CIF Quadtrees 、四角形の四辺形を四辺形の端にある二分木と組み合わせることで、任意の点集合の代わりに境界ボックスを格納します。
  • _ hamt _ 、含まれる定数のために一般にO(1)ハッシュマップを超えるアクセス時間を持つ階層型ハッシュマップ。
  • Inverted Index 、検索エンジン業界ではよく知られています。これは、さまざまな検索語に関連付けられている文書をすばやく検索するために使用されるためです。

全部ではないにしても、ほとんどはNISTに文書化されています アルゴリズムとデータ構造の辞書

18
Jasper Bekkers

実際にはデータ構造ではありません。動的に割り当てられた配列を最適化する方法はもっとありますが、Emacsで使われている gap buffer はとてもクールです。

17
kerkeslager

フェンウィックツリー与えられた2つのサブインデックスiとjの間で、ベクトル内のすべての要素の合計を数えるためのデータ構造です。開始時から項目の更新が許可されていないため、合計を事前に計算するのは簡単な解決策です(追いつくためにO(n)作業を行う必要があります)。

Fenwick TreesではO(log n)で更新や問い合わせができます。そしてそれがどのように機能するかは本当にクールでシンプルです。それはFenwickのオリジナルの論文で本当によく説明されていて、ここで自由に利用可能です:

http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol24/issue3/spe884.pdf

その父親であるRQMツリーも非常にクールです。ベクトルの2つのインデックス間の最小要素に関する情報を保持することができます。また、O(log n)の更新とクエリでも機能します。私は最初にRQM、そして次にフェンウィックツリーを教えるのが好きです。

16
eordano

Van Emde-Boasの木 。 2 ^ 20までの整数のために、私はC++ 実装 それを持っています。

14
zvrba

ネストされたセット は、リレーショナルデータベース内のツリーを表し、それらに対してクエリを実行するのに適しています。例えば、ActiveRecord(Ruby on RailsのデフォルトのORM)には、とてもシンプルな ネストされたset plugin が付属しています。

13
esad

展開されたリンクリスト は各ノードに複数の要素を格納するリンクリストのバリエーションです。参照などのリストメタデータの格納に関連するメモリオーバーヘッドを削減しながら、キャッシュパフォーマンスを大幅に向上させることができます。それはBツリーに関連しています。

record node {
    node next       // reference to next node in list
    int numElements // number of elements in this node, up to maxElements
    array elements  // an array of numElements elements, with space allocated for maxElements elements
}
12
marcog

スケープゴートの木。 普通の二分木に伴う古典的な問題は、それらが不均衡になることです(例えば、キーが昇順で挿入されるとき)

バランスのとれた二分木(AKA AVLツリー)はそれぞれの挿入の後に多くの時間のバランスをとることを浪費します。

赤黒木は均衡を保っていますが、各ノードに追加の記憶域が必要です。

スケープゴートの木は赤黒の木のようにバランスが取れていますが、追加のストレージは必要ありません。彼らはそれぞれの挿入の後に木を分析して、そして小さな調整をすることによってこれをする。 http://en.wikipedia.org/wiki/Scapegoat_tree を参照してください。

12
user20493

これはかなりドメイン固有ですが、 ハーフエッジデータ構造 はかなりきれいです。これは、ポリゴンメッシュ(faces および edges)を反復処理する方法を提供します。これは、コンピュータグラフィックおよび計算幾何学において非常に便利です。

12
mpen

2-3 Finger Trees by Hinze and Paterson は、広範囲の操作に対して優れた漸近性を持つ優れた機能データ構造のスイス軍ナイフです。複雑ではありますが、 再帰的なスローダウンによる連結を伴う永続リスト の前にあるカプランとタージャンによる命令型構造よりもはるかに単純です。

これらは、O(1)いずれかの端へのアクセス、O(log min(n,m))追加、およびシーケンスの任意の部分でのモニダル接頭辞合計への直接アクセスによるO(log min(n,length - n))インデックス付けを使用したcatenable dequeとして機能します。

HaskellCoqF#ScalaJava 、- CClojureC# およびその他の言語。

これらを使用して、 優先検索キュー間隔マップ高速ヘッドアクセスのロープ 、マップ、セット、 シーケンスを有効化)を実装できます。 または、すぐに有効化/インデックス化可能なシーケンスで monoidal の結果を収集すると表現できる構造。

また、いくつかの スライド があり、それらの派生と使用について説明しています。

11
Edward KMETT

あまり知られていませんが、かなり気の利いたデータ構造は Fenwick TreeBinary Indexed Tree またはBITとも呼ばれる)です。累積和を格納し、O(log(n))操作をサポートします。累積和はそれほど興奮しないかもしれませんが、それはsort/log(n)データ構造を必要とする多くの問題を解決するために適応させることができます。

IMO、その主なセールスポイントは、 実装 であることができる容易さです。そうでなければ赤黒/ avlツリーをコーディングすることを含むであろうアルゴリズムの問​​題を解決することにおいて非常に役に立ちます。

10
MAK

ペアリングヒープ は比較的単純な実装と優れた実用的な償却パフォーマンスを持つ一種のヒープデータ構造です。

10
Marko Tintor

XORリンクリスト は、二重リンクリストの記憶要件を減らすために2つのXORポインタを使用します。あいまいだがきれいな種類のもの!

10
yonkeltron

私は本当に 区間木 が大好きです。それらはあなたがたくさんの間隔(すなわち開始/終了時間、あるいは何でも)を取り、どの間隔が与えられた時間を含んでいるか、あるいはどの間隔が与えられた期間中に「アクティブ」であったかを問い合わせることを可能にします。問い合わせはO(log n)で行うことができ、前処理はO(n log n)です。

10
Jonathan

スプラッシュテーブル は素晴らしいです。これらは通常のハッシュテーブルに似ていますが、一定時間のルックアップを保証し、パフォーマンスを失うことなく90%の使用率を処理できるという点が異なります。それらは Cuckoo Hash の一般化です(/これも素晴らしいデータ構造です)。それらは 特許取得済み のように見えますが、ほとんどの純粋なソフトウェア特許と同じように私はあまり心配しないでしょう。

9
David Seiler

拡張ハッシュアルゴリズムは非常に興味深いものです。 線形ハッシュ は、テーブル全体を再ハッシュするのではなく、ハッシュテーブル内の「バケット」を一度に1つずつ分割することができるため、きれいです。これは分散キャッシュに特に役立ちます。ただし、ほとんどの単純な分割ポリシーでは、すべてのバケットをすばやく連続して分割することになり、テーブルの負荷率はかなり変動します。

私は スパイラルハッシング も本当にきれいだと思います。線形ハッシュと同様に、一度に1つのバケットが分割され、そのバケット内の半分以下のレコードが同じ新しいバケットに入れられます。とても清潔で速いです。ただし、各「バケット」が同じ仕様のマシンでホストされていると、効率が悪くなる可能性があります。ハードウェアを最大限に活用するには、より強力なマシンとより強力ではないマシンの組み合わせが必要です。

8
erickson

リージョン四分木

ウィキペディア から引用)

領域四分木は、各リーフノードが特定の小領域に対応するデータを含むように、領域を4つの等しい四分円、小四分円などに分解することによって、二次元で空間の区画を表す。ツリー内の各ノードは、正確に4つの子を持つか、またはまったく子を持ちません(リーフノード)。

このような四分木は、空間データを保存するのに適しています。緯度と経度、またはその他の種類の座標。

これは大学では私のお気に入りのデータ構造でした。この男をコーディングしてそれが機能するのを見るのはかなりクールでした。あなたが何らかの考えを持っていて、ちょっと殴られた道から少し離れているプロジェクトを探しているなら、私はそれを強く勧めます。とにかく、それはあなたが通常あなたのデータ構造クラスで割り当てられている標準的なBST派生物よりずっと楽しいです!

実際、おまけとして、私は講義からクラスプロジェクト(Virginia Techから)に至るまでのメモを見つけました ここ(pdf warning)

8
Andrew Whitaker

二分決定グラフ 私のお気に入りのデータ構造の1つ、または実際には縮小順序二分決定グラフ(ROBDD).

これらの種類の構造は、例えば以下の目的で使用できます。

  • 項目の集合を表し、それらの集合に対して非常に高速な論理操作を実行します。
  • 式のすべての解を求めることを目的とした任意のブール式

多くの問題はブール式として表現できることに注意してください。たとえば、sudukuの解はブール式として表現できます。そしてそのブール式のBDDを構築することはすぐに解決策を生み出すでしょう。

8
Zuu

私はtreapsが好きです - それをバランスさせるために二分探索木の上にランダムな優先順位でヒープ構造を重ね合わせるという単純でありながら効果的な考えのために。

7
Rafał Dowgird

Fast Compactが試みます:

6
bill

範囲を格納するために Inversion LIsts を使用することもありますが、それらは文字クラスを正規表現で格納するためによく使用されます。例えば、 http://www.ibm.com/developerworks/linux/library/l-cpinv.html を参照してください。

もう1つのナイスユースケースは、加重ランダム決定です。シンボルとそれに関連する確率のリストがあり、これらの確率に従ってそれらをランダムに選びたいとしましょう。

 a => 0.1 
 b => 0.5 
 c => 0.4 

それからあなたはすべての確率のランニング合計をする:

(0.1、0.6、1.0)

これがあなたの転置リストです。 0から1の間の乱数を生成し、リスト内で次に高いエントリのインデックスを見つけます。それはソートされているので、あなたは二分探索でそれをすることができます。インデックスを取得したら、元のリストでシンボルを調べることができます。

nシンボルがある場合は、O(n)準備時間があり、ランダムに選ばれた各シンボルについてO(log(n))アクセス時間があります。 。

反転リストのバリエーションでは、範囲の終点を示すために負の数を使用します。これにより、特定の点で重複する範囲の数を数えやすくなります。例については http://www.perlmonks.org/index.pl?node_id=841368 を参照してください。

6
moritz

_ dawg _ sは、似たような子ツリーが単一の親に圧縮される特殊な種類のTrieです。私は修正されたDAWGを拡張し、ASSDAWG(Anagram Search Sorted DAWG)と呼ばれる気の利いたデータ構造を思いついた。これがうまくいく方法は、文字列がDAWGに挿入されるときはいつでも、最初にバケツでソートされ、それから挿入され、リーフノードは 追加番号 を持ちます。 。これには2つの気の利いた利点があります。

  1. 挿入前に文字列をソートし、DAWGが自然に似たサブツリーを折りたたむので、高レベルの圧縮が得られます(例: "eat"、 "ate"、 "tea"はすべて1パスになります)。 AETのどの順列が有効か).
  2. 与えられた文字列のアナグラムを検索することは、ルートから葉へのパスが置換数を用いて葉ノードでそのパスのすべての有効なアナグラムを保持するので、今や超高速で簡単です。
6
pathikrit

ソートされていないバランスのとれたbtrees。

テキストエディタのバッファに最適です。

http://www.chiark.greenend.org.uk/~sgtatham/algorithms/cbtree.html

6
user82238

Arne Andersson trees は、赤黒の木に代わる単純なもので、正しいリンクだけが赤になります。これにより、赤黒の木と同等のパフォーマンスを維持しながら、メンテナンスが大幅に簡素化されます。オリジナルの論文は挿入と削除のために 素敵で短い実装 を与えています。

6
huitseeker

フェンウィックツリー (またはバイナリインデックスツリー)は、ツールキットに追加する価値があります。あなたがカウンタの配列を持っていて、累積カウントを問い合わせている間にそれらを絶えず更新する必要があるなら(PPM compressionのように)、FenwickツリーはO(log n)時間ですべての操作をし、余分なスペースを必要としません。よい導入については topcoder tutorial も参照してください。

5

Zobrist Hashing は(チェスのように)ゲームボードの位置を表すために一般的に使われるハッシュ関数ですが、確かに他の用途があります。 1つ良いことは、ボードが更新されるたびに段階的に更新できることです。

5
Fantius

BK-Trees、またはBurkhard-Keller Trees は、文字列に近いものをすばやく見つけるために使用できるツリーベースのデータ構造です。

5
Ashish

接尾辞treeが好き および 配列 文字列処理、 スキップリスト /バランスリストおよび スプレイツリー 自動バランスツリー

5
Antonio

Donald Knuthによって提示された横方向のヒープを見てください。

http://stanford-online.stanford.edu/seminars/knuth/071203-knuth-300.asx

5
4
Vaibhav Bajpai

スプレイの木はかっこいいです。最も頻繁に照会される要素をルートの近くに移動する方法で、自分自身を並べ替えます。

4
mdm

B *ツリー

これは、より高価な挿入を犠牲にして検索するのに効率的な、さまざまなBツリーです。

4
karlphillip

最小ヒープを使って一定の時間内に最小要素を見つけることも、最大ヒープを使って最大要素を見つけることもできます。しかし、両方の操作をしたい場合はどうなりますか? Min-Max を使用すると、両方の操作を一定時間で実行できます。これは、最小最大順序付けを使用して機能します。連続するツリーレベル間での最小ヒープ比較と最大ヒープ比較を交互に行います。

4
Firas Assaad

これらすべてのグラフ構造から離れて、私は単純な Ring-Buffer が大好きです。

正しく実装されていれば、パフォーマンスを維持しながら、場合によってはメモリのフットプリントを大幅に削減できます。

4
user97214

ブルームフィルタの言及によると、削除可能ブルームフィルタ(DlB​​F)は、基本的な集計方法よりも優れています。 http://arxiv.org/abs/1005.0352 を参照してください。

4
user201295

2つのスタックを使用して実装されたキューはかなりスペース効率的です(少なくとも1つの追加のポインタ/参照オーバーヘッドを持つリンクリストを使用するのとは対照的に)。

2つのスタックを使用してキューを実装する方法

キューが巨大なときにこれは私にはうまくいきました。私がポインタに8バイトを節約するならば、それは百万のエントリを持つキューが約8MBのRAMを節約することを意味します。

3
dhruvbird

三分探索木

  • クイックプレフィックス検索(インクリメンタルオートコンプリートなど)
  • 部分一致(文字列のXハミング距離内にあるすべての単語を検索する場合)
  • ワイルドカード検索

非常に簡単に実装できます。

3
st0le

優先順位付けは、異なる順序で2つの別々の優先順位キューを維持する必要があるよりも安くなります。 http://www.alexandria.ucsb.edu/middleware/javadoc/edu/ucsb/adl/middleware/PriorityDeque.htmlhttp://cphstl.dk/Report/Priority-deque/ cphstl-report-2001-14.pdf

3
ade

スキップリストは実際にはかなり素晴らしいです: http://en.wikipedia.org/wiki/Skip_list

3
DanC89

Paolo FerraginaとGiovanni Manziniによる FM-index は本当にクールだと思います。特にバイオインフォマティクスにおいて。これは基本的に、サフィックス配列と参照テキストのburrows-wheeler変換の組み合わせを利用した、圧縮されたフルテキストインデックスです。インデックス全体を解凍せずにインデックスを検索できます。

3
GWW
2
Gregable

このデータ構造に名前があるかどうかはわかりませんが、Boostに含めるために提案された tokenmap データ構造は興味深いものです。これは、ルックアップがO(1)だけではなく、単純な配列アクセスである、動的にサイズ変更可能なマップです。私は バックグラウンド素材 の大部分をこのデータ構造について書いた。それはそれがどのように機能するかの背後にある基本原理を説明している。

トークンマップのようなものは、ファイルまたはリソースハンドルをファイルまたはリソースを表すデータ構造にマッピングするためにオペレーティングシステムによって使用されます。

2
Daniel Trebbien

適切な文字列データ構造ほとんどすべてのプログラマは、言語がその構造に対して持っているどんなネイティブサポートでも解決します。それは通常非効率的です(特に文字列を構築するためには、別のクラスか何かが必要です)。

最悪の場合、文字列をCの文字配列として扱い、安全のためにNULLバイトに依存します。

2
Rudolf Olah

私は個人的には疎行列のデータ構造が非常に興味深いと思います。 http://www.netlib.org/linalg/html_templates/node90.html

有名なBLAS図書館はこれらを使用しています。そして、100,000の行と列を含む線形システムを扱うとき、これらを使うことが重要になります。これらの中には、コンピュータグラフィックで一般的なコンパクトグリッド(基本的にはバケットソートグリッドのようなもの)にも似たものがあります。 http://www.cs.kuleuven.be/~ares/publications/LD08CFRGRT/LD08CFRGRT.pdf

また、コンピュータグラフィックスに関する限り、MACグリッドはやや興味深いものですが、それはそれらが巧妙なためだけです。 http://www.seas.upenn.edu/~cis665/projects/Liquation_665_Report.pdf

2
CJJ

コーナーステッチのデータ構造 。要約から:

コーナーステッチングは、長方形の2次元オブジェクトを表現するための技法です。これは、VLSIレイアウト用の対話型編集システムに特に適しているようです。データ構造には、2つの重要な機能があります。まず、空きスペースが明示的に表されます。そして第二に、長方形の領域はパッチワークのキルトのようにそれらの角で一緒にステッチされています。この編成により、検索、作成、削除、ストレッチ、および圧縮のための高速アルゴリズム(線形時間以上)が得られます。アルゴリズムはVLSI回路の単純化されたモデルの下で提示され、そして構造の記憶要件は議論される。測定によると、コーナーステッチには、最も単純な表現の約3倍のメモリ容量が必要です。

2
Trey Jackson

Burrows – Wheeler変換 (ブロックソート圧縮)

圧縮に不可欠なアルゴリズムテキストファイルの行を圧縮したいとしましょう。行を並べ替えると情報が失われると言うでしょう。しかし、BWTはこのように機能します。入力をソートして整数インデックスを元の順序に戻すことで、エントロピーを大幅に削減します。

2

集合フォレストの分離 高速なメンバーシップクエリと和集合操作を許可します。 Kruskalのアルゴリズムで最もよく使用されます 最小全域木に対して。

本当にクールなことは、両方の演算が Ackermann関数 inverse に比例して実行時間を償却し、これが「最速」の不定時間データ構造になることです。

2
hugomg

デルタリスト/デルタキューは、cronやイベントシミュレータなどのプログラムで、次のイベントが発生したときに解決するために使用されます。 http://everything2.com/title/delta+listhttp://www.cs.iastate.edu/~cs554/lec_notes/delta_clock.pdf

2
ade

バケット旅団

それらはApacheで広く使われています。基本的にそれらは輪の中でそれ自身の周りをループするリンクリストです。それらがApacheおよびApacheモジュールの外部で使用されているかどうかはわかりませんが、それらはクールでありながらあまり知られていないデータ構造として法案を満たしています。バケツはいくつかの任意のデータのためのコンテナです、そして、バケツ旅団はバケツの集まりです。その考え方は、構造のどの時点でもデータを変更および挿入できるようにしたいということです。

バケット1文字あたり1文字のHTMLドキュメントを含むバケット旅団があるとしましょう。あなたはすべての<>シンボルを&lt;&gt;エンティティに変換したいです。バケツリレーでは、エンティティに必要な余分な文字に合うように、<または>シンボルに遭遇したときに、余分なバケツをブリゲードに挿入できます。バケツリレーはリング状になっているため、前後に挿入できます。これは単純なバッファを使用するよりもはるかに簡単です(C)。

以下のバケット旅団に関するいくつかの参照:

Apache Bucket Brigadeリファレンス

バケツと旅団の紹介

2
John Scipione

PATRICIA - 英数字でコード化された情報を検索するための実用的なアルゴリズム、D.R.Morrison(1968)。

PATRICIAツリーはトライに関連しています。トライの問題は、キーの集合がまばらであるとき、すなわち実際のキーが潜在的なキーの集合の小さなサブセットを形成するとき、非常によくあることですが、トライの内部ノードの多く(ほとんど)は子孫これにより、Trieはスペースが非常に複雑になります。

http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Tree/PATRICIA/ /

2
juancn

ハーフエッジデータ構造 および 翼付きエッジ ポリゴンメッシュの場合。

計算幾何学アルゴリズムに有用です。

1
habeanf

他の誰かがすでにBurkhard-Keller-Treesを提案しましたが、私は自分の実装をプラグインするためにそれらに再び言及するかもしれないと思いました。 :)

http://well-adjusted.de/mspace.py/index.html

より高速な実装があります(ActiveStateのPythonレシピまたは他の言語による実装を参照)。しかし、私のコードがこれらのデータ構造を理解するのに役立つと思います。

ちなみに、BKとVPの両方のツリーは、類似した文字列を検索するよりもはるかに多くの用途に使用できます。いくつかの条件(陽性、対称性、三角形の不等式)を満たす距離関数がある限り、任意のオブジェクトに対して類似性検索を実行できます。

1
Jochen
  • 二分決定グラフ(私のお気に入りのデータ構造。ブール方程式を表現し、それらを解くのに適しています。たくさんのことに有効です)
  • ヒープ(ノードの親が常にノードの子に対して何らかの関係を維持するツリー。ノードの親は常にその各子よりも大きい(max-heap))
  • 優先度キュー(実際には最小ヒープと最大ヒープのみ。そこにある多数の要素の順序を維持するのに適しています。例えば、最も高い値を持つアイテムが最初に削除されることになっています)
  • (すべてのルックアップ戦略の種類、及びバケットオーバーフロー処理と)ハッシュテーブル、
  • 平衡二分探索木(これらのそれぞれが独自の利点を有する).____。】
    • RBツリー(全体的に良い、順序付けられた方法で挿入、検索、削除、および反復を行う場合)
    • AVL木(RBよりも検索の高速化が、RBとそうでない場合は非常に似ています)
    • スプレイ木(最近使用したノードが再利用される可能性が高いとき、ルックアップのための高速化)
    • (より良い検索時間を取得するための高速な乗算を活用)融合ツリー
    • B +ツリー(データベースおよびファイルシステムでのインデックス作成に使用されます。インデックスに対して読み書きを行うための待ち時間が重要な場合に非常に効率的です)。
  • 空間インデックス(点/円/長方形/線/立方体が互いに近接しているか、または含まれているかどうかを問い合わせるのに優れています)。
    • BSPツリー
    • 四分木
    • オクトリー
    • 範囲ツリー
    • 似ているがわずかに異なる木がたくさんあり、大きさが異なる
  • 区間木(重なっている区間の良い発見、線形)
  • グラフ
    • 隣接リスト(エッジの基本的リスト)
    • 隣接行列(Edgeあたり1ビットでグラフの有向辺を表すテーブル。グラフトラバースの場合は非常に高速)

これらは私が考えるようになることができるものです。ウィキペディアには データ構造についての詳細があります

1
Zuu

私は WPL Trees を使って幸運を祈りました。枝の加重経路長を最小にする木の変形。重みはノードアクセスによって決定されるため、頻繁にアクセスされるノードはルートの近くに移動します。私は一度もそれらを使ったことがないので、それらがどうやってスプレイツリーと比較されるかわからない。

1
TMN

Cycle Sort はかなりきれいなソートアルゴリズムだと思います。

書き込みの合計数を最小限に抑えるために使用されるソートアルゴリズムです。フラッシュメモリの寿命が書き込み量に比例するフラッシュメモリを扱う場合、これは特に便利です。これは ウィキペディアの記事 ですが、最初のリンクに行くことをお勧めします。 (素敵な映像)

1
jyt

二項ヒープ にはたくさんの興味深い性質がありますが、そのうち最も有用なものはマージです。

1
DShook

環境追跡再帰構造.

コンパイラは再帰的な構造を使用しますが、ツリーのようなものではありません。内側のスコープは外側のスコープへのポインタを持っているので、入れ子は裏返しになります。変数がスコープ内にあるかどうかを検証することは、内側のスコープから外側のスコープへの再帰呼び出しです。

public class Env
{    
    HashMap<String, Object> map;
    Env                     outer;

    Env()
    {
        outer = null;
        map = new HashMap();
    }

    Env(Env o)
    {
        outer = o;
        map = new HashMap();
    }

    void put(String key, Object value)
    {
        map.put(key, value);
    }

    Object get(String key)
    {
        if (map.containsKey(key))
        {
            return map.get(key);
        }
        if (outer != null)
        {
            return outer.get(key);
        }
        return null;
    }

    Env Push()
    {
        return new Env(this);
    }

    Env pop()
    {
        return outer;
    }
}

この構造にも名前があるかどうかわからない。私はそれをインサイドアウトリストと呼んでいます。

1
Kelly S. French

配列を使用して要素のデータを保存する賢いデータ構造がありますが、配列はLinked-List/Arrayで一緒にリンクされています。

これには、要素に対する繰り返し処理が非常に高速で(純粋なリンクリストアプローチよりも高速)、メモリ内で要素を含む配列を移動するためのコストや(割り当て解除)割り当てが最小限で済むという利点があります。 (このため、このデータ構造はSimulationのものに役立ちます)。

私はここからそれについて知っています:

http://software.intel.com/en-us/blogs/2010/03/26/linked-list-verses-array/

「...そして、追加の配列が割り当てられ、パーティクルの配列のセルリストにリンクされています。これは、TBBがコンカレントコンテナを実装した方法といくつかの点で似ています。」 )

1
Quonux

直角三角形ネットワーク(RTIN)

メッシュを適応的に細分化するための非常にシンプルな方法。分割とマージ操作はそれぞれ数行のコードです。

0
Jon Harrop

RMQとLCAに関連するいくつかのアルゴリズムについて読んだとき、私は別のデータ構造に出会った デカルトツリー デカルトツリーでは、2つのノード間の最小共通祖先はそれらの間の最小ノードです。 RMQ問題をLCAに変換すると便利です。

0
jscoot