クイックリスト操作と注文クエリのためのデータ構造はありますか?


9

セットからの要素のリストのセットがあります。各要素は単一のリストに表示されます。次の更新を実行できるデータ構造を探しています。N = { 1 2 3 n } N LLN={1,2,3,...,n}NL

  1. concat(x,y):を含むリストをを含むリストの最後に連結しますxyx

  2. split(x):含むリスト分割直後xxx

また、次のクエリを実行する必要もあります。

  1. follows(x,y):とが同じリストにあり、が後に場合に返し(ただし、必ずしも隣接している必要はありません)x y y x xtruexyyxx

  2. first(x):を含むリストの最初の要素を返しx

  3. next(x):の後に戻り次の要素リストを含むでxxx

これらの更新をで実行し、クエリを時間で実行するデータ構造をすでに思いついています。私は主にこれを実行できるデータ構造が既にあるかどうかに興味があります(うまくいけばより速く?)。O l g n O(lg2(n))O(lg(n))

動機:根ざした有向フォレストは、これらのリストセットの2つで表すことができ、そのようなフォレストでの到達可能性をすばやく計算できます。私はそれらが他に何のために使用できるのか、そしてこれらすべてがすでに知られているのかどうかを見たいです。

回答:


11

スキップリストに整数を保持します。通常のスキップリストはキー順に並べられていますが、シーケンスの表現として使用します。さらに、サイズのポインターの配列を維持します。配列の各要素は、スキップリストのノードを指す必要があります。私は、このサポート信じるでと内の他のすべての操作。n e x t O 1 O lg n nnextO(1)O(lgn)

具体的には:

  • s p l i t O lg n O lg n concat2つのスキップリストをまたはすると、時間かかるため、多くてもポインタが無効になります。splitO(lgn)O(lgn)
  • O 1 nextは、リーフレベルで前方ポインタをたどり、時間かかります。O(1)
  • O lg n firstに時間かかります:行き詰まるまでポインタを追跡し、次に左ポインタを追跡します。左のポインタをこれ以上たどれないときは、スキップリストの先頭ポインタにいます。リーフへのポインタをたどり、次に1つの順方向ポインタをたどります。これはリストの最初の要素です。O(lgn)
  • f i r s t y x x y O lg n O lg n followsは少しトリッキーです。はと同じように進めますが、行き詰まっている場所(つまり、ポインタを追跡できなくなった場所)のリストを記録します。このリストを「トレース」と記録します。についても同じことを行いますが、立ち往生するときは、左ではなく右のポインタに従います。が前にある場合、それらのトレースは交差します。トレースのサイズはです。トレース内の各要素にスタックレベルの注釈が付けられている場合、時間交差をチェックできます。firstyxxyO(lgn)O(lgn)

O 1 O lg n nextは最悪の場合の、他のすべては高い確率でです。確定的なスキップリストを使用することで、最悪のケースにすることができます。O(1)O(lgn)

葉レベルでリンクされた(2,5)ツリーを使用し、スパインをブーストラッピングすることで、をできると思います。ブートストラップのトリックについては、KaplanおよびTarjanによる「Catenableのソートされたリストの純粋に機能的な表現」を参照してください。O lg lg n concatO(lglgn)


涼しい。私はスキップリストについて考えていましたが、関連するキー値なしでフォローする方法がよくわかりませんでした。
Sasho Nikolov、

これは素晴らしい; すべての更新を確定的にする方法がわかります。これは良いことです。O(lg lg(n))を理解するには、読み続けなければなりません。@jbappleの投稿に感謝します。O(lg(n))
bbejot

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