SkipList -----跳表

来源:互联网 发布:linux创建逻辑卷命令 编辑:程序博客网 时间:2024/06/06 01:51
今天学习了一个非常高效的数据结构,那就是跳表。其查找效率比红黑树要更高。整个的实现见下面:
//参考:Skip lists: a probabilistic alternative to balanced trees #ifndef _SKIPLIST_H_#define _SKIPLIST_H_#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#define MAX_L 16 //最大层数  //new_node生成一个Node结构体,同时生成包含n个Node *元素的数组#define new_node(n) ((Node*)malloc(sizeof(Node)+n*sizeof(Node*)))//定义key和value的类型 typedef int keyType;typedef int valueType;//每个节点的数据结构typedef struct node{    keyType key;// key值    valueType value;// value值    struct node *next[1];// 后继指针数组,柔性数组 可实现结构体的变长} Node;//跳表结构typedef struct skip_list{    int level;// 最大层数    Node *head;//指向头结点} skip_list;/*  创建节点,成功返回Node*类型指针,否则返回NULL  level 节点层数  key   节点关键字  vlal  节点的值*/Node *create_node(int level, keyType key, valueType val);/*  创建跳跃表,成功返回skip_list*类型指针,否则返回NULL*/skip_list *create_sl();/*插入元素的时候元素所占有的层数完全是随机算法,返回随机层数*/int randomLevel();/*  插入节点,插入成功返回true,否则返回false  sl     跳表指针  key   节点关键字  vlal  节点的值*/bool insert(skip_list *sl, keyType key, valueType val);/*  删除节点,成功返回true,否则返回false  sl     跳表指针  key   节点关键字*/bool erase(skip_list *sl, keyType key);/*  查找节点,成功返回valueT*类型的指针,否则返回NULL  sl     跳表指针  key   节点关键字*/valueType *search(skip_list *sl, keyType key);/*从最高层开始逐层打印sl 跳表指针*/void print_sl(skip_list *sl);/*释放跳跃表sl 跳表指针*/void sl_free(skip_list *sl);#endif
#include "skiplist.h"// 创建节点Node *create_node(int level, keyType key, valueType val){    Node *p=new_node(level);    if(!p)        return NULL;    p->key=key;    p->value=val;    return p;}//创建跳跃表skip_list *create_sl(){    skip_list *sl=(skip_list*)malloc(sizeof(skip_list));//申请跳表结构内存    if(NULL==sl)        return NULL;    sl->level=0;// 设置跳表的层level,初始的层为0层(数组从0开始)    Node *h=create_node(MAX_L-1, 0, 0);//创建头结点    if(h==NULL)    {        free(sl);        return NULL;    }    sl->head = h; // 将header的next数组清空    for(int i=0; i<MAX_L; ++i)    {        h->next[i] = NULL;    }srand(time(0));    return sl;}//插入元素的时候元素所占有的层数完全是随机算法int randomLevel(){int level=1;    while (rand()%2)        level++;    level=(MAX_L>level)? level:MAX_L;    return level;}/*step1:查找到在每层待插入位置,跟新update数组step2:需要随机产生一个层数step3:从高层至下插入,与普通链表的插入完全相同。*/bool insert(skip_list *sl, keyType key, valueType val){    Node *update[MAX_L];    Node *q=NULL,*p=sl->head;//q,p初始化    int i=sl->level-1;    /******************step1*******************/    //从最高层往下查找需要插入的位置,并更新update    //即把降层节点指针保存到update数组    for( ; i>=0; --i)    {        while((q=p->next[i])&& q->key<key)            p=q;        update[i]=p;    }    if(q && q->key == key)//key已经存在的情况下    {        q->value = val;        return true;    }    /******************step2*******************/    //产生一个随机层数level    int level = randomLevel();    //如果新生成的层数比跳表的层数大    if(level>sl->level)    {//在update数组中将新添加的层指向header        for(i=sl->level; i<level; ++i)        {            update[i]=sl->head;        }        sl->level=level;    }//printf("%d\n", sizeof(Node)+level*sizeof(Node*));    /******************step3*******************/    //新建一个待插入节点,一层一层插入    q=create_node(level, key, val);    if(!q)        return false;    //逐层更新节点的指针,和普通链表插入一样    for(i=level-1; i>=0; --i)    {        q->next[i]=update[i]->next[i];        update[i]->next[i]=q;    }    return true;}// 删除节点bool erase(skip_list *sl, keyType key){    Node *update[MAX_L];    Node *q=NULL, *p=sl->head;    int i = sl->level-1;    for(; i>=0; --i)    {        while((q=p->next[i]) && q->key < key){p=q;}        update[i]=p;    }    //判断是否为待删除的key    if(!q || (q&&q->key != key))        return false;    //逐层删除与普通链表删除一样    for(i=sl->level-1; i>=0; --i)    {        if(update[i]->next[i]==q)//删除节点        {            update[i]->next[i]=q->next[i];            //如果删除的是最高层的节点,则level--            if(sl->head->next[i]==NULL)                sl->level--;        }    }    free(q);q=NULL;    return true;}// 查找valueType *search(skip_list *sl, keyType key){    Node *q,*p=sl->head;q=NULL;    int i=sl->level-1;    for(; i>=0; --i)    {        while((q=p->next[i]) && q->key<key)        {            p=q;        }        if(q && key==q->key)            return &(q->value);    }    return NULL;}//从最高层开始逐层打印void print_sl(skip_list *sl){    Node *q;    int i=sl->level-1;    for(; i>=0; --i)    {        q=sl->head->next[i];        printf("level %d:\n", i+1);while(q)        {            printf("key:%d val:%d\t", q->key, q->value);            q=q->next[i];        }        printf("\n");    }}// 释放跳跃表void sl_free(skip_list *sl){    if(!sl)        return;    Node *q=sl->head;Node *next;while(q)    {next=q->next[0];free(q);q=next;    }    free(sl);}
#include "skiplist.h"int main(){    skip_list *sl=create_sl();int i=1;for(;i<1000; ++i){insert(sl, i, i+2);}for(i=11; i<111; ++i){if(!erase(sl, i))printf("No!\n");}print_sl(sl);int *p=search(sl, 10);if(p)printf("value of key 10 is %d\n", *p);sl_free(sl);    return 0;}


原创粉丝点击