博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Skip list--reference wiki
阅读量:6280 次
发布时间:2019-06-22

本文共 11582 字,大约阅读时间需要 38 分钟。

In , a skip list is a  that allows fast search within an  of elements. Fast search is made possible by maintaining a linked hierarchy of subsequences, each skipping over fewer elements. Searching starts in the sparsest subsequence until two consecutive elements have been found, one smaller and one larger than the element searched for. Via the linked hierarchy these two elements link to elements of the next sparsest subsequence where searching is continued until finally we are searching in the full sequence. The elements that are skipped over may be chosen probabilistically.

 

Properties: 

  Consists of several levels.
  All keys appear in level 1
  Each level is a sorted list.
  If key x appears in level i, then it also appears in all levels below i
  An element in level i points (via down pointer) to the element with the same key in the level below.
  In each level the keys -1 and 1 appear. (In our implementation, INT_MIN and INT_MAX
  Top points to the smallest element in the highest level.
 
cost:
  The expected number of levels is O( log n )    
   (here n  is the numer of elements)
  The expected time for insert/delete/find is O( log n )
  The expected size (number of cells) is O(n )
 
Skip List
List
Invented 1989
Invented by
in 
  Average Worst case
Space O(n) O(n log n)
Search O(log n) O(n)
Insert O(log n) O(n)
Delete O(log n) O(n)

Contents

 

Description

A skip list is built in layers. The bottom layer is an ordinary ordered . Each higher layer acts as an "express lane" for the lists below, where an element in layer i appears in layer i+1 with some fixed probability p (two commonly used values for p are 1/2 or 1/4). On average, each element appears in 1/(1-p) lists, and the tallest element (usually a special head element at the front of the skip list) in \log_{1/p} n\, lists.

A search for a target element begins at the head element in the top list, and proceeds horizontally until the current element is greater than or equal to the target. If the current element is equal to the target, it has been found. If the current element is greater than the target, or the search reaches the end of the linked list, the procedure is repeated after returning to the previous element and dropping down vertically to the next lower list. The expected number of steps in each linked list is at most 1/p, which can be seen by tracing the search path backwards from the target until reaching an element that appears in the next higher list or reaching the beginning of the current list. Therefore, the total expected cost of a search is (\log_{1/p} n)/p,\, which is \mathcal{O}(\log n)\, when p is a constant. By choosing different values of p, it is possible to trade search costs against storage costs.

Implementation details

Inserting elements to skip list

The elements used for a skip list can contain more than one pointer since they can participate in more than one list.

Insertions and deletions are implemented much like the corresponding linked-list operations, except that "tall" elements must be inserted into or deleted from more than one linked list.

\mathcal{O}(n) operations, which force us to visit every node in ascending order (such as printing the entire list), provide the opportunity to perform a behind-the-scenes derandomization of the level structure of the skip-list in an optimal way, bringing the skip list to \mathcal{O}(\log n) search time. (Choose the level of the i'th finite node to be 1 plus the number of times we can repeatedly divide i by 2 before it becomes odd. Also, i=0 for the negative infinity header as we have the usual special case of choosing the highest possible level for negative and/or positive infinite nodes.) However this also allows someone to know where all of the higher-than-level 1 nodes are and delete them.

Alternatively, we could make the level structure quasi-random in the following way:

make all nodes level 1j ← 1while the number of nodes at level j > 1 do  for each i'th node at level j do    if i is odd       if i is not the last node at level j        randomly choose whether to promote it to level j+1      else        do not promote      end if    else if i is even and node i-1 was not promoted      promote it to level j+1    end if  repeat  j ← j + 1repeat

Like the derandomized version, quasi-randomization is only done when there is some other reason to be running a \mathcal{O}(n) operation (which visits every node).

The advantage of this quasi-randomness is that it doesn't give away nearly as much level-structure related information to an  as the de-randomized one. This is desirable because an adversarial user who is able to tell which nodes are not at the lowest level can pessimize performance by simply deleting higher-level nodes. The search performance is still guaranteed to be logarithmic.

It would be tempting to make the following "optimization": In the part which says "Next, for each i'th...", forget about doing a coin-flip for each even-odd pair. Just flip a coin once to decide whether to promote only the even ones or only the odd ones. Instead of \mathcal{O}(n \log n) coin flips, there would only be \mathcal{O}(\log n) of them. Unfortunately, this gives the adversarial user a 50/50 chance of being correct upon guessing that all of the even numbered nodes (among the ones at level 1 or higher) are higher than level one. This is despite the property that he has a very low probability of guessing that a particular node is at level N for some integer N.

A skip list does not provide the same absolute worst-case performance guarantees as more traditional  data structures, because it is always possible (though with very low probability) that the coin-flips used to build the skip list will produce a badly balanced structure. However, they work well in practice, and the randomized balancing scheme has been argued to be easier to implement than the deterministic balancing schemes used in balanced binary search trees. Skip lists are also useful in , where insertions can be done in different parts of the skip list in parallel without any global rebalancing of the data structure. Such parallelism can be especially advantageous for resource discovery in an ad-hoc  because a randomized skip list can be made robust to the loss of any single node.

There has been some evidence that skip lists have worse real-world performance and space requirements than  due to  and other issues.

Indexable skiplist

As described above, a skiplist is capable of fast \mathcal{O}(\log n) insertion and removal of values from a sorted sequence, but it has only slow \mathcal{O}(n) lookups of values at a given position in the sequence (i.e. return the 500th value); however, with a minor modification the speed of  indexed lookups can be improved to \mathcal{O}(\log n).

For every link, also store the width of the link. The width is defined as the number of bottom layer links being traversed by each of the higher layer "express lane" links.

For example, here are the widths of the links in the example at the top of the page:

1                               10 o---> o---------------------------------------------------------> o    Top level   1           3              2                    5 o---> o---------------> o---------> o---------------------------> o    Level 3   1        2        1        2                    5 o---> o---------> o---> o---------> o---------------------------> o    Level 2   1     1     1     1     1     1     1     1     1     1     1  o---> o---> o---> o---> o---> o---> o---> o---> o---> o---> o---> o    Bottom level                                        Head  1st   2nd   3rd   4th   5th   6th   7th   8th   9th   10th  NIL      Node  Node  Node  Node  Node  Node  Node  Node  Node  Node

Notice that the width of a higher level link is the sum of the component links below it (i.e. the width 10 link spans the links of widths 3, 2 and 5 immediately below it). Consequently, the sum of all widths is the same on every level (10 + 1 = 1 + 3 + 2 + 5 = 1 + 2 + 1 + 2 + 5).

To index the skiplist and find the i'th value, traverse the skiplist while counting down the widths of each traversed link. Descend a level whenever the upcoming width would be too large.

For example, to find the node in the fifth position (Node 5), traverse a link of width 1 at the top level. Now four more steps are needed but the next width on this level is ten which is too large, so drop one level. Traverse one link of width 3. Since another step of width 2 would be too far, drop down to the bottom level. Now traverse the final link of width 1 to reach the target running total of 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

This method of implementing indexing is detailed in .

History

Skip lists were first described in 1990 by .

To quote the author:

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.

Usages

List of applications and frameworks that use skip lists:

  •  offers a "skiplist" backend DB implementation ()
  •  uses skip lists to search delta-encoded posting lists in logarithmic time.
  •  (up to Qt 4) template class of  that provides a dictionary.
  • , an ANSI-C open-source persistent key/value store for Posix systems, uses skip lists in its implementation of ordered sets.
  • , a very fast key-value embedded Database Storage Engine (Using log-structured-merge (LSM) trees), uses skip lists for its memtable.
  •  is an open-source database format using ordered key/value pairs.
  •  and  in the Java 1.6 API.
  • , a fast key-value storage library written at Google that provides an ordered mapping from string keys to string values
  •  of  (also known as moving medians).

Skip lists are also used in distributed applications (where the nodes represent physical computers, and pointers represent network connections) and for implementing highly scalable concurrent priority queues with less lock contention, or even without locking, as well lockless concurrent dictionaries. There are also several US patents for using skip lists to implement (lockless) priority queues and concurrent dictionaries.[]

See also

  • Skip trees, an alternative data structure to Skip lists in a concurrent approach: 
  • Skip tree graphs: , 

References

  1. ^   
  2. ^    (1990). .  33 (6): 668. :. 
  3.  
  4.  Shah, Gauri Ph.D.; James Aspnes (December 2003).  (PDF). Retrieved 2008-09-23.
  5.  
  6.  .
  7.  Shavit, N.; Lotan, I. (2000). . Proceedings 14th International Parallel and Distributed Processing Symposium. IPDPS 2000. p. 263.:.  . 
  8.  Sundell, H.; Tsigas, P. (2003). "Fast and lock-free concurrent priority queues for multi-thread systems". Proceedings International Parallel and Distributed Processing Symposium. p. 11. :.  . 
  9.  Fomitchev, M.; Ruppert, E. (2004). "Lock-free linked lists and skip lists". Proceedings of the twenty-third annual ACM symposium on Principles of distributed computing - PODC '04. p. 50. :.  . 
  10.  Bajpai, R.; Dhara, K. K.; Krishnaswamy, V. (2008). "QPID: A Distributed Priority Queue with Item Locality". 2008 IEEE International Symposium on Parallel and Distributed Processing with Applications. p. 215. :.  . 
  11.  Sundell, H. K.; Tsigas, P. (2004). . Proceedings of the 2004 ACM symposium on Applied computing - SAC '04. p. 1438.:.  . 

External links

  •  in the 
  •  on  in C# 2.0
Demo applets
  •  by Kubo Kovac
Implementations
  •  by Antonio Gulli
  •  (and )

转载地址:http://mbiva.baihongyu.com/

你可能感兴趣的文章
Java Mail最基本的发送邮件例子
查看>>
《HTML 5与CSS 3 权威指南(第3版·上册)》——2.3 新增的属性和废除的属性
查看>>
《Total Commander:万能文件管理器》——第3.5节.选择文件
查看>>
《日志管理与分析权威指南》一导读
查看>>
去 TMD 互联网思维,性价比而已
查看>>
如何手动删除Oracle 11g数据库
查看>>
懒人促进社会进步 - 5种索引的原理和优化Case (btree,hash,gin,gist,brin)
查看>>
《深入实践Spring Boot》一3.4 视图设计
查看>>
《设计模式解析(第2版•修订版)》目录—导读
查看>>
《Web前端开发精品课 HTML与CSS进阶教程》——2.2 标题语义化
查看>>
Java核心技术卷I基础知识3.5.3 强制类型转换
查看>>
可与Mirai比肩的恶意程序Hajime,竟是为了保护IoT设备?
查看>>
《Spring Data 官方文档》6. Cassandra 存储库
查看>>
聊聊并发(十)生产者消费者模式
查看>>
R语言数据挖掘2.2.4.2 FP-growth算法
查看>>
人工智能概念诞生60年,哪些大牛堪称“一代宗师”?
查看>>
《游戏大师Chris Crawford谈互动叙事》一9.5 真实案例
查看>>
Mybatis与Spring整合连接MySQL
查看>>
GCC知识
查看>>
实验4 IIC通讯与EEPROM接口
查看>>