跳表(skiplist)是一个非常优秀的数据结构,实现简单,插入、删除、查找的复杂度均为O(logN)。LevelDB的核心数据结构是用跳表实现的,redis的sorted set数据结构也是有跳表实现的。
其结构如下所示:
所有操作均从上向下逐层查找,越上层一次next操作跨度越大。其实现是典型的空间换时间。
具体的细节,可参考维基百科 http://en.wikipedia.org/wiki/Skip_list
 
本文作者将redis的sorted set代码进行整理,将跳表部分的实现抽取出来,供参考。
skiplist.h
InBlock.gif#ifndef __SKIPLIST_H
InBlock.gif #define __SKIPLIST_H
InBlock.gif    
InBlock.gif #define SKIPLIST_MAXLEVEL 8    
InBlock.gif    
InBlock.gif typedef struct skiplistNode {
InBlock.gif         double score;
InBlock.gif         struct skiplistNode *backward;
InBlock.gif         struct skiplistLevel {
InBlock.gif                 struct skiplistNode *forward;
InBlock.gif         }level[];
InBlock.gif }skiplistNode;
InBlock.gif    
InBlock.gif typedef struct skiplist {
InBlock.gif         struct skiplistNode *header, *tail;
InBlock.gif         unsigned long length;
InBlock.gif         int level;
InBlock.gif }skiplist;
InBlock.gif    
InBlock.gif #endif
skiplist.c
InBlock.gif#include "skiplist.h"
InBlock.gif #include <stdlib.h>
InBlock.gif #include <stdio.h>
InBlock.gif    
InBlock.gif skiplistNode *slCreateNode( int level, double score) {
InBlock.gif         skiplistNode * sn = malloc( sizeof(*sn) + level* sizeof( struct skiplistLevel));
InBlock.gif         sn->score = score;
InBlock.gif         return sn;
InBlock.gif }
InBlock.gif    
InBlock.gif skiplist *slCreate( void) {
InBlock.gif         int j;
InBlock.gif         skiplist *sl;
InBlock.gif    
InBlock.gif         sl = malloc( sizeof(*sl));
InBlock.gif         sl->level = 1;
InBlock.gif         sl->length = 0;
InBlock.gif         sl->header = slCreateNode(SKIPLIST_MAXLEVEL, 0);
InBlock.gif         for(j = 0; j < SKIPLIST_MAXLEVEL; j++) {
InBlock.gif                 sl->header->level[j].forward = NULL;
InBlock.gif         }
InBlock.gif         sl->header->backward = NULL;
InBlock.gif         sl->tail = NULL;
InBlock.gif         return sl;
InBlock.gif }
InBlock.gif    
InBlock.gif void slFreeNode(skiplistNode *sn) {
InBlock.gif         free(sn);
InBlock.gif }
InBlock.gif    
InBlock.gif void slFree(skiplist *sl) {
InBlock.gif         skiplistNode *node = sl->header->level[0].forward, *next;
InBlock.gif    
InBlock.gif         free(sl->header);
InBlock.gif         while(node) {
InBlock.gif                 next = node->level[0].forward;
InBlock.gif                 slFreeNode(node);
InBlock.gif                 node = next;
InBlock.gif         }
InBlock.gif         free(sl);
InBlock.gif }
InBlock.gif    
InBlock.gif int slRandomLevel( void) {
InBlock.gif         int level = 1;
InBlock.gif         while((rand()&0xFFFF) < (0.5 * 0xFFFF))    
InBlock.gif                 level += 1;
InBlock.gif         return (level < SKIPLIST_MAXLEVEL) ? level : SKIPLIST_MAXLEVEL;
InBlock.gif }
InBlock.gif    
InBlock.gif skiplistNode *slInsert(skiplist *sl, double score) {
InBlock.gif         skiplistNode *update[SKIPLIST_MAXLEVEL];
InBlock.gif         skiplistNode *node;
InBlock.gif    
InBlock.gif         node = sl->header;
InBlock.gif         int i, level;
InBlock.gif         for ( i = sl->level-1; i >= 0; i--) {
InBlock.gif                 while(node->level[i].forward && node->level[i].forward->score < score) {
InBlock.gif                         node = node->level[i].forward;
InBlock.gif                 }
InBlock.gif                 update[i] = node;
InBlock.gif         }
InBlock.gif         level = slRandomLevel();
InBlock.gif         if (level > sl->level) {
InBlock.gif                 for (i = sl->level; i< level ;i++) {
InBlock.gif                         update[i] = sl->header;
InBlock.gif                 }
InBlock.gif                 sl->level = level;
InBlock.gif         }
InBlock.gif         node = slCreateNode(level, score);
InBlock.gif         for (i = 0; i < level; i++) {
InBlock.gif                 node->level[i].forward = update[i]->level[i].forward;
InBlock.gif                 update[i]->level[i].forward = node;
InBlock.gif         }
InBlock.gif    
InBlock.gif         node->backward = (update[0] == sl->header? NULL : update[0]);
InBlock.gif         if (node->level[0].forward)
InBlock.gif                 node->level[0].forward->backward = node;
InBlock.gif         else
InBlock.gif                 sl->tail = node;
InBlock.gif         sl->length++;
InBlock.gif         return node;
InBlock.gif }
InBlock.gif    
InBlock.gif void slDeleteNode(skiplist *sl, skiplistNode *x, skiplistNode **update){
InBlock.gif         int i;
InBlock.gif         for (i = 0; i < sl->level; i++) {
InBlock.gif                 if (update[i]->level[i].forward == x) {
InBlock.gif                         update[i]->level[i].forward = x->level[i].forward;
InBlock.gif                 }
InBlock.gif         }
InBlock.gif         if (x->level[0].forward) {
InBlock.gif                 x->level[0].forward->backward = x->backward;
InBlock.gif         } else {
InBlock.gif                 sl->tail = x->backward;
InBlock.gif         }
InBlock.gif         while (sl->level > 1 && sl->header->level[sl->level-1].forward == NULL)    
InBlock.gif                 sl->level--;
InBlock.gif         sl->length--;
InBlock.gif }
InBlock.gif    
InBlock.gif int slDelete(skiplist *sl, double score) {
InBlock.gif         skiplistNode *update[SKIPLIST_MAXLEVEL], *node;
InBlock.gif         int i;
InBlock.gif    
InBlock.gif         node = sl->header;
InBlock.gif         for(i = sl->level-1; i >= 0; i--) {
InBlock.gif                 while (node->level[i].forward && node->level[i].forward->score < score) {
InBlock.gif                         node = node->level[i].forward;
InBlock.gif                 }
InBlock.gif                 update[i] = node;
InBlock.gif         }
InBlock.gif         node = node->level[0].forward;
InBlock.gif         if (node && score == node->score) {
InBlock.gif                 slDeleteNode(sl, node, update);
InBlock.gif                 slFreeNode(node);
InBlock.gif                 return 1;
InBlock.gif         } else {
InBlock.gif                 return 0;
InBlock.gif         }
InBlock.gif         return 0;
InBlock.gif }
InBlock.gif    
InBlock.gif int slSearch(skiplist *sl, double score) {
InBlock.gif         skiplistNode *node;
InBlock.gif         int i;
InBlock.gif    
InBlock.gif         node = sl->header;
InBlock.gif         for (i = sl->level-1; i >= 0 ;i--) {
InBlock.gif                 while(node->level[i].forward && node->level[i].forward->score < score) {
InBlock.gif                         node = node->level[i].forward;
InBlock.gif                 }
InBlock.gif         }
InBlock.gif         node = node->level[0].forward;
InBlock.gif         if (node && score == node->score) {
InBlock.gif                 printf( "Found %d\n",( int)node->score);
InBlock.gif                 return 1;
InBlock.gif         } else {
InBlock.gif                 printf( "Not found %d\n", ( int)score);
InBlock.gif                 return 0;
InBlock.gif         }
InBlock.gif }
InBlock.gif    
InBlock.gif void slPrint(skiplist *sl) {
InBlock.gif         skiplistNode *node;
InBlock.gif         int i;
InBlock.gif         for (i = 0; i < SKIPLIST_MAXLEVEL; i++) {
InBlock.gif                 printf( "LEVEL[%d]: ", i);
InBlock.gif                 node = sl->header->level[i].forward;
InBlock.gif                 while(node) {
InBlock.gif                         printf( "%d -> ", ( int)(node->score));
InBlock.gif                         node = node->level[i].forward;
InBlock.gif                 }
InBlock.gif                 printf( "NULL\n");
InBlock.gif         }
InBlock.gif }
InBlock.gif    
InBlock.gif #ifdef SKIP_LIST_TEST_MAIN
InBlock.gif int main() {
InBlock.gif         srand((unsigned)time(0));
InBlock.gif         int count = 20, i;
InBlock.gif    
InBlock.gif         printf( "### Function Test ###\n");
InBlock.gif    
InBlock.gif         printf( "=== Init Skip List ===\n");
InBlock.gif         skiplist * sl = slCreate();
InBlock.gif         for ( i = 0; i < count; i++) {
InBlock.gif                 slInsert(sl,i);
InBlock.gif         }
InBlock.gif         printf( "=== Print Skip List ===\n");
InBlock.gif         slPrint(sl);
InBlock.gif    
InBlock.gif         printf( "=== Search Skip List ===\n");
InBlock.gif         for (i = 0; i < count; i++) {
InBlock.gif                 int value = rand()%(count+10);
InBlock.gif                 slSearch(sl, value);
InBlock.gif         }
InBlock.gif         printf( "=== Delete Skip List ===\n");
InBlock.gif         for (i = 0; i < count+10; i+=2) {
InBlock.gif                 printf( "Delete[%d]: %s\n", i, slDelete(sl, i)? "SUCCESS": "NOT FOUND");
InBlock.gif         }
InBlock.gif         slPrint(sl);
InBlock.gif    
InBlock.gif         slFree(sl);
InBlock.gif         sl = NULL;
InBlock.gif }
InBlock.gif #endif
测试结果如下所示:
### Function Test ###
=== Init Skip List ===
=== Print Skip List ===
LEVEL[0]: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> 11 -> 12 -> 13 -> 14 -> 15 -> 16 -> 17 -> 18 -> 19 -> NULL
LEVEL[1]: 0 -> 2 -> 4 -> 7 -> 9 -> 10 -> 11 -> 12 -> 14 -> 15 -> 17 -> 18 -> NULL
LEVEL[2]: 7 -> 10 -> 12 -> 14 -> 15 -> NULL
LEVEL[3]: 10 -> 14 -> 15 -> NULL
LEVEL[4]: 10 -> 14 -> NULL
LEVEL[5]: NULL
LEVEL[6]: NULL
LEVEL[7]: NULL
=== Search Skip List ===
Found 1
Found 18
Not found 21
Not found 24
Found 10
Not found 20
Found 14
Found 10
Found 19
Found 18
Not found 27
Found 5
Found 0
Found 0
Found 18
Not found 26
Found 13
Not found 28
Not found 29
Not found 23
=== Delete Skip List ===
Delete[0]: SUCCESS
Delete[2]: SUCCESS
Delete[4]: SUCCESS
Delete[6]: SUCCESS
Delete[8]: SUCCESS
Delete[10]: SUCCESS
Delete[12]: SUCCESS
Delete[14]: SUCCESS
Delete[16]: SUCCESS
Delete[18]: SUCCESS
Delete[20]: NOT FOUND
Delete[22]: NOT FOUND
Delete[24]: NOT FOUND
Delete[26]: NOT FOUND
Delete[28]: NOT FOUND
LEVEL[0]: 1 -> 3 -> 5 -> 7 -> 9 -> 11 -> 13 -> 15 -> 17 -> 19 -> NULL
LEVEL[1]: 7 -> 9 -> 11 -> 15 -> 17 -> NULL
LEVEL[2]: 7 -> 15 -> NULL
LEVEL[3]: 15 -> NULL
LEVEL[4]: NULL
LEVEL[5]: NULL
LEVEL[6]: NULL
LEVEL[7]: NULL