跳跃表skiplist

1、简介

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

基本上,跳跃列表是对有序的链表增加上附加的前进链接,增加是以随机化的方式进行的,所以在列表中的查找可以快速的跳过部分列表,因此得名。所有操作都以对数随机化的时间进行。

跳跃列表由 William Pugh 发明。他在 Communications of the ACM June 1990, 33(6) 668-676 发表了 Skip lists: a probabilistic alternative to balanced trees,在其中详细描述了他的工作。引用发明者的话:
跳跃列表是在很多应用中有可能替代平衡树而作为实现方法的一种数据结构。跳跃列表的算法有同平衡树一样的渐进的预期时间边界,并且更简单、更快速和使用更少的空间。
 
典型的跳跃表结构如下:

跳跃表数据结构:

 1 #define MAX_LEVEL   31
 2 
 3 struct node
 4 {
 5     int key;
 6     int value;
 7     struct node *forward[1];
 8 };
 9 
10 struct skiplist
11 {
12     int level;
13     struct node *list_head;
14 };
15 
16 #define NIL list->list_head 

初始化:

 1 int skiplist_init(struct skiplist *list)
 2 {
 3     int i;
 4     list->list_head = (struct node *)malloc(sizeof(struct node) + MAX_LEVEL * sizeof(struct node *));
 5     if (list->list_head == NULL)
 6         return -1; 
 7 
 8     for (i = 0; i <= MAX_LEVEL; i++)
 9         list->list_head->forward[i] = NIL;
10     list->level = 0;
11     return 0;
12 }

2、跳表操作

2.1 查找

  如下图,查找12时的查找路径

 1 int skiplist_find(struct skiplist *list, int key, int *value)
 2 {
 3     int i, level_new;
 4     struct node *pn = NULL;
 5 
 6     /* find insert position */
 7     pn = list->list_head;
 8     for (i = list->level; i >= 0; i--)
 9     {   
10         while ((pn->forward[i] != NIL) && (pn->forward[i]->key < key))
11             pn = pn->forward[i];
12     }   
13     pn = pn->forward[0];
14     if ((pn != NIL) && (pn->key == key))
15     {   
16         *value = pn->value;
17         return 0;
18     }   
19     
20     return -1; 
21 }

 

2.2 插入

插入17时的路径如图,需要

a) 找到插入位置

b) 更新forward

 1 int skiplist_insert(struct skiplist *list, int key, int value)
 2 {
 3     int i, level_new;
 4     struct node *update[MAX_LEVEL + 1] = {NULL};
 5     struct node *pn = NULL;
 6 
 7     /* find insert position */
 8     pn = list->list_head;
 9     for (i = list->level; i >= 0; i--)
10     {
11         while ((pn->forward[i] != NIL) && (pn->forward[i]->key < key))
12             pn = pn->forward[i];
13         update[i] = pn;
14     }
15     pn = pn->forward[0];
16     if ((pn != NIL) && (pn->key == key))
17         return -1;
18 
19     /* determine level */
20     for (level_new = 0; (rand() < RAND_MAX / 2) && (level_new < MAX_LEVEL); level_new++);
21 
22     if (level_new > list->level)
23     {
24         for (i = list->level + 1; i <= level_new; i++)
25             update[i] = NIL;
26         list->level = level_new;
27     }
28 
29     /* make new node */
30     pn = (struct node *)malloc(sizeof(struct node) + list->level * sizeof(struct node *));
31     if (pn == NULL)
32         return -1;
33     pn->key = key;
34     pn->value = value;
35 
36     /* update forward links */
37     for (i = 0; i <= level_new; i++)
38     {
39         pn->forward[i] = update[i]->forward[i];
40         update[i]->forward[i] = pn;
41     }
42 
43     return 0;
44 }

 

2.3 删除

 1 int skiplist_delete(struct skiplist *list, int key)
 2 {
 3     int i, level_new;
 4     struct node *update[MAX_LEVEL + 1] = {NULL};
 5     struct node *pn = NULL;
 6 
 7     /* find insert position */
 8     pn = list->list_head;
 9     for (i = list->level; i >= 0; i--)
10     {
11         while ((pn->forward[i] != NIL) && (pn->forward[i]->key < key))
12             pn = pn->forward[i];
13         update[i] = pn;
14     }
15     pn = pn->forward[0];
16     if ((pn == NIL) || (pn->key != key))
17         return -1;
18 
19     /* adjust forward pointers */
20     for (i = 0; i <= list->level; i++)
21     {
22         if (update[i]->forward[i] != pn)
23             break;
24         update[i]->forward[i] = pn->forward[i];
25     }
26 
27     free(pn);
28 
29     /* adjust list level */
30     while ((list->level > 0) && (list->list_head->forward[list->level] == NIL))
31         list->level--;
32 
33     return 0;
34 }

2.4 跳跃表遍历

 1 void skiplist_show(struct skiplist *list)
 2 {
 3     int i;
 4     int table[MAX_LEVEL + 1] = {0};
 5     struct node *pn = NULL;
 6 
 7     for (i = 0; i <= list->level; i++)
 8     {
 9         pn = list->list_head;
10         printf("%d level:\n", i);
11         while (pn->forward[i] != NIL)
12         {
13             pn = pn->forward[i];
14 #ifdef FULL_LIST
15             printf("<%d> -> ", pn->key);
16 #endif
17             table[i]++;
18         }
19         printf("Total %d nodes\n", table[i]);
20     }
21 
22 }

3、调表性能分析

 

你可能感兴趣的:(跳跃表skiplist)