跳跃表(Skip List)-实现(Java)

文章转自:http://www.acmerblog.com/skip-list-impl-java-5773.html

跳跃表是一种随机化数据结构,基于并联的链表,其效率可比拟于二叉查找树(对于大多数操作需要O(log n)平均时间),并且对并发算法友好。

关于跳跃表的具体介绍可以参考MIT的公开课:跳跃表

跳跃表的应用

Skip list(跳表)是一种可以代替平衡树的数据结构,默认是按照Key值升序的。Skip list让已排序的数据分布在多层链表中,以0-1随机数决定一个数据的向上攀升与否,通过“空间来换取时间”的一个算法,在每个节点中增加了向前的指针,在插入、删除、查找时可以忽略一些不可能涉及到的结点,从而提高了效率。

在Java的API中已经有了实现:分别是

ConcurrentSkipListMap(在功能上对应HashTable、HashMap、TreeMap) ;

ConcurrentSkipListSet(在功能上对应HashSet). 

确切来说,SkipList更像Java中的TreeMapTreeMap基于红黑树(一种自平衡二叉查找树)实现的,时间复杂度平均能达到O(log n)。

HashMap是基于散列表实现的,时间复杂度平均能达到O(1)。ConcurrentSkipListMap是基于跳表实现的,时间复杂度平均能达到O(log n)。

Skip list的性质

(1) 由很多层结构组成,level是通过一定的概率随机产生的。
(2) 每一层都是一个有序的链表,默认是升序
(3) 最底层(Level 1)的链表包含所有元素。
(4) 如果一个元素出现在Level i 的链表中,则它在Level i 之下的链表也都会出现。
(5) 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。

Ø  ConcurrentSkipListMap具有Skip list的性质 ,并且适用于大规模数据的并发访问。多个线程可以安全地并发执行插入、移除、更新和访问操作。与其他有锁机制的数据结构在巨大的压力下相比有优势。

Ø  TreeMap插入数据时平衡树采用严格的旋转(比如平衡二叉树有左旋右旋)来保证平衡,因此Skip list比较容易实现,而且相比平衡树有着较高的运行效率。

Java代码实现:

1. SkipListEntry.java , 这是跳跃表中存储的每个元素实体类,包含 上下左右 四个指针。

01 package skiplist;
02  
03 public class SkipListEntry {
04     public String key;
05     public Integer value;
06  
07     public int pos; //主要为了打印 链表用
08  
09     public SkipListEntry up, down, left, right; // 上下左右 四个指针
10  
11     public static String negInf = new String("-oo"); // 负无穷
12     public static String posInf = new String("+oo"); // 正无穷
13  
14     public SkipListEntry(String k, Integer v) {
15         key = k;
16         value = v;
17  
18         up = down = left = right = null;
19     }
20  
21     public Integer getValue() {
22         return value;
23     }
24  
25     public String getKey() {
26         return key;
27     }
28  
29     public Integer setValue(Integer val) {
30         Integer oldValue = value;
31         value = val;
32         return oldValue;
33     }
34  
35     public boolean equals(Object o) {
36         SkipListEntry ent;
37         try {
38             ent = (SkipListEntry) o; // 检测类型
39         catch (ClassCastException ex) {
40             return false;
41         }
42         return (ent.getKey() == key) && (ent.getValue() == value);
43     }
44  
45     public String toString() {
46         return "(" + key + "," + value + ")";
47     }
48 }

2. SkipList.java, 跳跃表类,包含算法的实现。 head 和 tail 分别是 顶层的头和尾。

001 package skiplist;
002  
003 import java.util.*;
004  
005 public class SkipList {
006     public SkipListEntry head; // 顶层的第一个元素
007     public SkipListEntry tail; // 顶层的最后一个元素
008  
009     public int n; // 跳跃表中的元素个数
010  
011     public int h; // 跳跃表的高度
012     public Random r; // 投掷硬币
013  
014     public SkipList() // 默认构造函数...
015     {
016         SkipListEntry p1, p2;
017  
018         p1 = new SkipListEntry(SkipListEntry.negInf, null);
019         p2 = new SkipListEntry(SkipListEntry.posInf, null);
020  
021         head = p1;
022         tail = p2;
023  
024         p1.right = p2;
025         p2.left = p1;
026  
027         n = 0;
028         h = 0;
029         r = new Random();
030     }
031  
032     /** 返回 包含的元素个数 */
033     public int size() {
034         return n;
035     }
036  
037     /** 跳跃表是否为空 */
038     public boolean isEmpty() {
039         return (n == 0);
040     }
041  
042      //在最下面一层,找到要插入的位置前面的那个key
043     public SkipListEntry findEntry(String k) {
044         SkipListEntry p;
045         p = head;
046  
047         while (true) {
048             /**
049              * 一直向右找,例: k=34.
050              * 10 ---> 20 ---> 30 ---> 40 ^ | p 会在30处停止
051              * --------------------------------------------
052              ***/
053             while (p.right.key != SkipListEntry.posInf
054                     && p.right.key.compareTo(k) <= 0) {
055                 p = p.right;
056             //  System.out.println(">>>> " + p.key);
057             }
058             // 如果还有下一层,就到下一层继续查找
059             if (p.down != null) {
060                 p = p.down;
061                  //System.out.println("vvvv " + p.key);
062             else
063                 break// 到了最下面一层 就停止查找
064         }
065  
066         return (p); // p.key <= k
067     }
068  
069     /** 返回和key绑定的值 */
070     public Integer get(String k) {
071         SkipListEntry p;
072  
073         p = findEntry(k);
074  
075         if (k.equals(p.getKey()))
076             return (p.value);
077         else
078             return (null);
079     }
080  
081     /** 放一个key-value到跳跃表中, 替换原有的并返回 */
082     public Integer put(String k, Integer v) {
083         SkipListEntry p, q;
084         int i;
085  
086         p = findEntry(k);
087  
088         if (k.equals(p.getKey())) {
089             Integer old = p.value;
090             p.value = v;
091             return (old);
092         }
093  
094         q = new SkipListEntry(k, v);
095         q.left = p;
096         q.right = p.right;
097         p.right.left = q;
098         p.right = q;
099  
100         i = 0// 当前层 level = 0
101  
102         while (r.nextDouble() < 0.5) {
103  
104             //如果超出了高度,需要重新建一个顶层
105             if (i >= h) {
106                 SkipListEntry p1, p2;
107  
108                 h = h + 1;
109                 p1 = new SkipListEntry(SkipListEntry.negInf, null);
110                 p2 = new SkipListEntry(SkipListEntry.posInf, null);
111  
112                 p1.right = p2;
113                 p1.down = head;
114  
115                 p2.left = p1;
116                 p2.down = tail;
117  
118                 head.up = p1;
119                 tail.up = p2;
120  
121                 head = p1;
122                 tail = p2;
123             }
124  
125             while (p.up == null) {
126                 p = p.left;
127             }
128             p = p.up;
129  
130             SkipListEntry e;
131  
132             e = new SkipListEntry(k, null);
133             e.left = p;
134             e.right = p.right;
135             e.down = q;
136  
137             p.right.left = e;
138             p.right = e;
139             q.up = e;
140  
141             q = e; // q 进行下一层迭代
142             i = i + 1// 当前层 +1
143  
144         }
145         n = n + 1;
146  
147         return (null); // No old value
148     }
149  
150     

你可能感兴趣的:(数据结构,链表,跳跃表)