An implementation of Skip list

来源:互联网 发布:python socketserver 编辑:程序博客网 时间:2024/05/16 07:10

随着redis和leveldb的火爆,Skip List(跳表)也火了起来,关于skip list的基础,自己google。skip list和B树、红黑树之类的平衡树有着同样的效果,但是skip list是一种超级简单而优雅的结构,实现B树,我们可能需要查阅很多资料,考虑很多细节,但是跳表完全可以在半个小时之类完成。

    下面是我的实现,有参考了网上的一些代码:

#ifndef SKIPLIST_H_#define SKIPLIST_H_#include <stdio.h>#include <stdlib.h>#include <time.h>#define MAXLEVEL 24             /*max level of the skip list*/                                /*the number of the MAXLEVEL is up to the dataset*/typedef int T;        /*define the type of the data to be stored*/typedef struct _Node{T data;struct _Node *next[1];      /*next[i] point to the next node in level i*/}Node;typedef struct _skiplist{int levelnum;    /*current level number of the skip list*/int num[MAXLEVEL];          /*the number of nodes of each level*/Node *head;    /*head point to a Node of max level next[]*/}skiplist;skiplist list;#define END list.headvoid init(){list.head = (Node *)malloc(sizeof(Node) + (MAXLEVEL-1)*sizeof(Node*));int i;for(i=0; i<MAXLEVEL; i++){list.head->next[i] = END;list.num[i] = 0;}list.levelnum = -1;}int find(T data){Node *x = list.head;int i;for(i=list.levelnum; i>=0; i--){while(x->next[i]!=END && x->next[i]->data<data)x = x->next[i];}if(x->next[0]!=END && x->next[0]->data==data)return 1;return 0;}Node *insert(T data){Node *x = list.head;Node *pre[MAXLEVEL];int i;for(i=list.levelnum; i>=0; i--){                  /*find the position to insert*/while(x->next[i]!=END && x->next[i]->data<data)x = x->next[i];pre[i] = x;                                   /*record the pre-insert position of each level*/ }if(x->next[0]!=END && x->next[0]->data==data)return x->next[0];int insertLevel =0;  /*generate a random insert level*///while(rand()%2==1 && ++insertLevel<MAXLEVEL-1); /*rand()%2 ==1, the insertlevel can never reach 16,why??*/ while(rand()<RAND_MAX/2 && ++insertLevel<MAXLEVEL-1);if(insertLevel > list.levelnum){for(i=insertLevel; i>list.levelnum; i--){pre[i] = END;}list.levelnum = insertLevel;}Node *newNode = (Node *)malloc(sizeof(Node) + (insertLevel)*sizeof(Node *));newNode->data = data;for(i=insertLevel; i>=0; i--){newNode->next[i] = pre[i]->next[i];pre[i]->next[i] = newNode;list.num[i]++;}return newNode;}void remove(T data){Node *x = list.head;Node *pre[MAXLEVEL];int i;for(i=list.levelnum; i>=0; i--){               /*find the position to delete*/while(x->next[i]!=END && x->next[i]->data<data)x = x->next[i];pre[i] = x;                                /*record the pre-insert position of each level*/ }if(x->next[0]==END || x->next[0]->data!=data)return;x = x->next[0];/*WOW...Wow...!!!!!, x->next[0] should be stored in x, otherwile  x->next[0] will be modified by pre[]*/for(i=0; i<=list.levelnum; i++){if(pre[i]->next[i] != x)break;pre[i]->next[i] = x->next[i];list.num[i]--;}free(x);for(i=list.levelnum; i>=0; i--){              /*update the levelnum, discard the empty level*/if(list.head->next[i]!=END)break;list.levelnum--;}}void printlist(){int i;for(i=list.levelnum; i>=0; i--){Node *x = list.head;printf("%d  Head--->",i);while(x->next[i] != END){printf("%d---->",x->next[i]->data);x = x->next[i];}printf("End\n\n");}}void printOneLevel(int level){if(level > list.levelnum){printf("level is valid(larger than the current level of the list\n");return;}Node *x = list.head;printf("%d  Head--->",level);while(x->next[level] != END){printf("%d---->",x->next[level]->data);x = x->next[level];}printf("End\n\n");}#endif



#include <stdio.h>#include <stdlib.h>#include <string.h>#include "skiplist.h"#define TESTNUM 20extern skiplist list;int main(){srand(time(0));init();//for(int i=0; i<TESTNUM; i++)//insert(rand()%TESTNUM);//insert(2);//insert(2);//insert(9);////printf("%d,%d\n",list.levelnum,find(2));//printlist();//for(int i=list.levelnum; i>=0; i--)//printf("%d--->%d\n",i,list.num[i]);//remove(2);//remove(9);//remove(10);//printf("-----------------------------------\n");//printlist();//for(int i=list.levelnum; i>=0; i--)//printf("%d--->%d\n",i,list.num[i]);printf("---------------------\n");while(1){char cmd[10];int data;scanf("%s",cmd);if(!strcmp(cmd,"insert")||!strcmp(cmd,"i")){scanf("%d",&data);insert(data);}else if(!strcmp(cmd,"remove")||!strcmp(cmd,"r")){scanf("%d",&data);remove(data);}else if(!strcmp(cmd,"find")||!strcmp(cmd,"f")){scanf("%d",&data);if(find(data)){printf("success\n");}else{printf("failed\n");}}else if(!strcmp(cmd,"print")||!strcmp(cmd,"p")){printlist();}else if(!strcmp(cmd,"quit")||!strcmp(cmd,"q")){break;}elseprintf("command %s is not valid!\n",cmd);}return 0;}



代码看起来没有多少,但是对于长时间没有编程的我还是花了不少时间(虽然参考了别人的代码)。

收获:

1. next[1] 结构发在struct的后面,可以任意长数组,(动态申请一个next为max的Node,sizeof(Node)+(max-1)*sizeof(Node*))

typedef struct _Node{T data;struct _Node *next[1];      /*next[i] point to the next node in level i*/}Node;

2. remove()中,对x=x->next[0]这个地方,花了我半个小时找问题,,原来,如果如果没有这句,x就是保存的前面的Node而x->next[0]在后面被改变了,在调用就指向了错误的地方!!!

总之,就是【指针指向的地方在后面被改变了】,这个要小心,常常注意不到!!!!




0 0
原创粉丝点击