コンテンツにスキップ

「スキップリスト」の版間の差分

出典: フリー百科事典『ウィキペディア(Wikipedia)』
削除された内容 追加された内容
→‎Implementation details: 英語版( 22:17, 20 April 2017‎ )を元に追記・修正
ウィリアム・ピューをリンク化
 
(7人の利用者による、間の8版が非表示)
4行目: 4行目:

|-

|-

! 種類

! 種類

| colspan="2" | [[リスト]]

| colspan="2" | [[リスト (抽象データ型)|リスト]]

|-

|-

! 考案者

! 考案者

35行目: 35行目:

|}

|}



'''スキップリスト'''({{lang-en-short|skip list}})は、[[平衡二分探索木]]と似た用途に使う[[乱択アルゴリズム]]の[[データ構造]]。[[連結リスト]]を並列に連結させて作る。比較により順序づけ可能な要素を挿入し、スキップリスト内では[[ソート]]された状態で保持される。ソートされた[[連想配列]]や[[集合]]の実装などに使える。挿入と探索と削除は平均O(log ''n'')である。1989年に[[:en:William Pugh|William Pugh]]が発表した<ref>{{cite journal

'''スキップリスト'''({{lang-en-short|skip list}})は、[[平衡二分探索木]]と似た用途に使う[[乱択アルゴリズム]]の[[データ構造]]。[[連結リスト]]を並列に連結させて作る。比較により順序づけ可能な要素を挿入し、スキップリスト内では[[ソート]]された状態で保持される。ソートされた[[連想配列]]や[[集合]]の実装などに使える。挿入と探索と削除は平均O(log ''n'')である。1989年に[[ウィリアム・ピュー (計算機科学者)|ウィリアム・ピュー]]が発表した<ref>{{cite journal

| last=Pugh

| last=Pugh

| first=William

| first=William

75行目: 75行目:


== 説明 ==

== 説明 ==

スキップリストはリストの階層になっている。最下層は通常のソートされた[[連結リスト]]である。それより上の層は、それぞれ下のリストに対する「急行列車」のように働き、層''i'' に存在するリストの要素は層''i+1'' においては固定の確率''p''(良く使われる ''p'' の値は 1/2 と 1/4)で存在する。各要素は平均で 1/(1-''p'')個のリストに属し、最も背の高い要素、つまり普通スキップリストの先頭の特別扱いされる要素はすべてのリストに属する。スキップリストは <math> \log_{1/p} n \,</math>個の連結リストを含む。

スキップリストはリストの階層になっている。最下層は通常のソートされた[[連結リスト]]である。それより上の層は、それぞれ下のリストに対する「急行列車」のように働き、層''i'' に存在するリストの要素は層''i+1'' においては固定の確率''p''(良く使われる ''p'' の値は 1/2 と 1/4)で存在する。各要素は平均で 1/(1-''p'')個のリストに属し、最も背の高い要素、つまり普通スキップリストの先頭の特別扱いされる要素はすべてのリストに属する。スキップリストは <math> \log_{1/p} n \,</math>個の連結リストを含む<!-- $1+\log_{1/p}n$では? $p\to 0$の極限で最も背の高い要素の高さが1でないとおかしいと思う


第$i(>1)$層に存在する要素の数の期待値が$np^{i-1}$となり、層を上がる毎に要素の数が減るから、最上層の高さの期待値を$h$とすると$np^{h-1} \leq 1$すなわち$h \leq 1+\log_{1/p}n$ が成り立つように思う。 -->。



目的の要素を探索するには、まず、最上層の連結リストの先頭の要素から(水平方向に)スキャンして、目的の要素と同じかそれより大きい要素を探し出す。もし、探し出した要素が目的の要素と等しいならば、探索は完了。もし、探し出した要素が目的の要素より大きいならば、あるいは、リストの最後の要素に到達してしまった場合は、一つ前の要素に戻ってから一つ下の層の連結リストに(垂直方向に)降り、そのリストに対して同じ操作を繰り返す。各連結リストにおいてリンクを辿る数の期待値は最大でも 1/''p'' となる。これは目的の要素から逆向きに戻って上層のリストにつながる要素に到達するまでの期待値であることから理解できる。従って探索の総コストは <math>(\log_{1/p} n)/p\,</math>で、''p''を固定すれば<math>\mathcal{O}(\log n)\,</math>である。''p''にさまざまな値を選ぶことで、探索時間とメモリ使用量の[[トレードオフ]]をとることが可能である。

目的の要素を探索するには、まず、最上層の連結リストの先頭の要素から(水平方向に)スキャンして、目的の要素と同じかそれより大きい要素を探し出す。もし、探し出した要素が目的の要素と等しいならば、探索は完了。もし、探し出した要素が目的の要素より大きいならば、あるいは、リストの最後の要素に到達してしまった場合は、一つ前の要素に戻ってから一つ下の層の連結リストに(垂直方向に)降り、そのリストに対して同じ操作を繰り返す。各連結リストにおいてリンクを辿る数の期待値は最大でも 1/''p'' となる。これは目的の要素から逆向きに戻って上層のリストにつながる要素に到達するまでの期待値であることから理解できる。従って探索の総コストは <math>(\log_{1/p} n)/p\,</math>で、''p''を固定すれば<math>\mathcal{O}(\log n)\,</math>である。''p''にさまざまな値を選ぶことで、探索時間とメモリ使用量の[[トレードオフ]]をとることが可能である。



=== Implementation details ===

=== 実装の詳細 ===

スキップリストで用いられる要素はつ以上のポインタを含む可能性があるが、それは、つ以上のリストに属している可能性があるからである。

スキップリストで用いられる要素は1つ以上のポインタを含む可能性があるが、それは、1つ以上のリストに属している可能性があるからである。



挿入と削除は、[[連結リスト]]の対応する操作と同様の実装になるが、"背の高い"要素は2つ以上の連結リストに対して挿入及び削除する必要がある。

挿入と削除は、[[連結リスト]]の対応する操作と同様の実装になるが、"背の高い"要素は2つ以上の連結リストに対して挿入及び削除する必要がある。

92行目: 94行目:

検索時間については、ランダム性の無い場合と同様、対数時間であることが保証されている。

検索時間については、ランダム性の無い場合と同様、対数時間であることが保証されている。




i1<math> \mathcal{O} ( n \log n ) </math>  <math> \mathcal{O} ( \log n ) </math>  1501

, i1<math> \mathcal{O} ( n \log n ) </math>  <math> \mathcal{O} ( \log n ) </math> 1'''1'''50



<!-- 21nn11/21n-11n11/2n1n-11n-2123nk212-->

<!-- 21nn11/21n-11n11/2n1n-11n-2123nk212-->

<!-- ランダマイズされていない場合は高さが1, 2, 1, 2といった具合に配置されているが、ランダマイズされている場合は2, 1, 1, 2と配置されることがある。 -->

<!-- ランダマイズされていない場合は高さが1, 2, 1, 2といった具合に配置されているが、ランダマイズされている場合は2, 1, 1, 2と配置されることがある。 -->




<!-- k21/2222231/231/4k1/(2^(k-1))-->

<!-- k21/2222231/231/4k1/(2^(k-1))-->


スキップリストは、より伝統的な平衡木と同じ最悪時のパフォーマンスを保証しない。なぜなら、(確率はとても低いが)バランスの悪い構造になる場合が常にあるからである。しかし実際にはよく動作し、ランダム化されたバランスとりの仕組みは平衡二分探索木の決定論的なバランスとりの仕組みより実装が容易であることが示されている。スキップリストは並列計算においても有用で、挿入はスキップリストのいくつかの部分で並列に実施でき、全体のリバランスが不要である。この並列化は、アドホック無線ネットワークでのリソース探索において特に有用となりうる。なぜなら、ランダム性のあるスキップリストは単一ノード損失に対して堅牢にすることができるからである。


[[ ()|]][[]]


メモリアクセスの局所性の問題やその他の問題のため、スキップリストが実際の性能とメモリ効率において[[B木]]より悪いという証拠が存在する([http://resnet.uoregon.edu/~gurney_j/jmpc/skiplist.html])。

<!-- メモリアクセスの局所性の問題やその他の問題のため、スキップリストが実際の性能とメモリ効率において[[B木]]より悪いという証拠が存在する([http://resnet.uoregon.edu/~gurney_j/jmpc/skiplist.html])。-->


=== Indexable skiplist ===


上で述べられているように、スキップリストでは、データ系列への値の挿入や削除は高速に(<math>\mathcal{O}(\log n)</math>で)可能であるが、系列の中のある指定した場所の値の取り出し(例えば、500番目の値を返す)は遅く、<math>\mathcal{O}(n)</math> の時間がかかる。しかし、少し変更を加えることで、[[ランダムアクセス]] の実行時間は<math>\mathcal{O}(\log n)</math>にまで改良することができる。


すべてのリンクに対し、リンクの「幅」も格納することにする。ここでリンクの「幅」とは、「急行列車」のリンクが飛ばす(最下層での)リンクの数である。


例として、上で挙げた例のリンクの幅を次に示す。


1 10

o---> o---------------------------------------------------------> o 最上層

1 3 2 5

o---> o---------------> o---------> o---------------------------> o 第3層

1 2 1 2 3 2

o---> o---------> o---> o---------> o---------------> o---------> o 第2層

1 1 1 1 1 1 1 1 1 1 1

o---> o---> o---> o---> o---> o---> o---> o---> o---> o---> o---> o 最下層

''' '''

Head 1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th NIL

Node Node Node Node Node Node Node Node Node Node



2103325 (10 + 1 = 1 + 3 + 2 + 5 = 1 + 2 + 1 + 2 + 5)

スキップリストにインデクスをつけて ''i'' 番目の値を探すには、スキップリスト内を、進んだリンクの幅の分だけ必要ステップ数を減らしながら、リンクを辿っていけばよい。次のリンク幅が大きすぎる場合には、下の層へ降りる。


例えば、上の例で5番目の値を得たい場合には、まず最上位層の幅1のリンクを進む。残りの必要ステップ数は 4=5-1 であるが、次のステップ幅は10であり大きすぎるので、第3層へ降りる。この層で、幅3のリンクを進む。 残りの必要ステップ数は1で、次のリンク幅は2のため大きすぎ、下の層へ降りる。第2層の次のリンクも幅が2で大きすぎるため、最下層に降りる。最後に幅1のリンクを1つ進めば、5(=1+3+1)ステップ進んだことになり、目的のノードにたどり着く。


'''function''' lookupByPositionIndex(i)

node ← head

i ← i + 1 ''# don't count the head as a step''

'''for''' level '''from''' top '''to''' bottom '''do'''

'''while''' i ? node.width[level] '''do''' ''# if next step is not too far''

i ← i - node.width[level] ''# subtract the current width''

node ← node.next[level] ''# traverse forward at the current level''

'''repeat'''

'''repeat'''

'''return''' node.value

'''end function'''


このインデクス付けの実装方法については、[http://cg.scs.carleton.ca/~morin/teaching/5408/refs/p90b.pdf Section 3.4 Linear List Operations in "A skip list cookbook" by William Pugh]に詳細がある。



==歴史==

==歴史==

160行目: 202行目:


==参照==

==参照==

{{reflist}}

{{Reflist}}



{{データ構造}}

{{データ構造}}


{{Computer-stub}}

{{Computer-stub}}




2021年10月26日 (火) 11:53時点における最新版

スキップリスト
種類 リスト
考案者 William Pugh
発表年 1989年
計算量ビッグ・オー記法
平均 最悪
空間計算量
探索の時間計算量
挿入の時間計算量
削除の時間計算量

: skip list使使O(log n)1989[1][2][3][4]

150%225%312.5%
110

[]


i i+1 p使 p 1/2  1/4 1/(1-p) 

辿 1/p  pp使

[]


11

""2

ii=m*2^nmn1i=0 

1i2222

(BetheaReiter使[5])

, i1  1150








Indexable skiplist[]


500  




   1                               10
 o---> o--------------------------------------------------------->o最上層
   1           3              2                    5
 o---> o---------------> o---------> o--------------------------->o3層
   1        2        1        2              3              2
 o---> o---------> o---> o---------> o---------------> o--------->o2層
   1     1     1     1     1     1     1     1     1     1     1
 o---> o---> o---> o---> o---> o---> o---> o---> o---> o---> o--->o最下層
                                         
Head  1st   2nd   3rd   4th   5th   6th   7th   8th   9th   10th  NIL
      Node  Node  Node  Node  Node  Node  Node  Node  Node  Node

2103325 (10 + 1 = 1 + 3 + 2 + 5 = 1 + 2 + 1 + 2 + 5)

 i辿

51 4=5-1 1033 1222115(=1+3+1)
 function lookupByPositionIndex(i)
     node ← head
     i ← i + 1                           # don't count the head as a step
     for level from top to bottom do
          while i ? node.width[level] do # if next step is not too far
              i ← i - node.width[level]  # subtract the current width
              node ← node.next[level]    # traverse forward at the current level
          repeat
     repeat
     return node.value
 end function

Section 3.4 Linear List Operations in "A skip list cookbook" by William Pugh

[]


Willam Pugh辿



Skip lists are a probabilistic data structure that seem likely to supplant balanced trees as the implementation method of choice for many applications. Skip list algorithms have the same asymptotic expected time bounds as balanced trees and are simpler, faster and use less space.

使[1]

[]


1990 William Pugh  A Skip List Cookbook[4] 

 - k O(log k) 



 - O(log n)





使

[]


12: skip quadtree: skip octree[6]使 O(log n)使 O(n)2005 David Eppstein [7]

kd

[]


P2P112003 James Aspnes [8]

[]


Java  Java 6  java.util.concurrent.ConcurrentSkipListSet[9]  ConcurrentSkipListMap[10] 

参照[編集]

  1. ^ Pugh, William (August 1989). “Skip lists: a probabilistic alternative to balanced trees”. Proceedings of the Workshop on Algorithms and Data Structures, Ottawa Canada. 
  2. ^ Pugh, William (June 1990). “Skip lists: a probabilistic alternative to balanced trees”. Communications of the ACM 33: 668-676. http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.17.9380. 
  3. ^ Pugh, William (1990). “Concurrent Maintenance of Skip Lists”. Univ. of Maryland Institute for Advanced Computer Studies Report No. UMIACS-TR-90-80 (University of Maryland at College Park). http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.17.8201. 
  4. ^ a b Pugh, William (1990). “A Skip List Cookbook”. Univ. of Maryland Institute for Advanced Computer Studies Report No. UMIACS-TR-89-72.1 (University of Maryland at College Park). http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.17.524. 
  5. ^ Bethea, Darrell; Reiter, Michael K. (21–23 September 2009). Data Structures with Unpredictable Timing (PDF). ESORICS 2009, 14th European Symposium on Research in Computer Security. Saint-Malo, France. pp. 456–471, §4 "Skip Lists". doi:10.1007/978-3-642-04444-1_28. ISBN 3-642-04443-3
  6. ^ J. R. Woodwark (1984). “Compressed Quad Trees”. Computer journal 27 (3): 225-229. http://comjnl.oxfordjournals.org/content/27/3/225.full.pdf. 
  7. ^ David Eppstein; Michael T. Goodrich; Jonathan Z. Sun (2005). “The Skip Quadtree: A Simple Dynamic Data Structure for Multidimensional Data”. SCG '05 Proceedings of the twenty-first annual symposium on Computational geometry: 296-305. doi:10.1145/1064092.1064138. http://arxiv.org/abs/cs/0507049. 
  8. ^ James Aspnes; Gauri Shah (2003). “Skip graphs”. Fourteenth Annual ACM-SIAM Symposium on Discrete Algorithms: 384–393. http://arxiv.org/abs/cs/0306043. 
  9. ^ ConcurrentSkipListSet (Java Platform SE 8 )
  10. ^ ConcurrentSkipListMap (Java Platform SE 8 )