simple skiplist implementation in c

来源:互联网 发布:数据库的类型有哪些 编辑:程序博客网 时间:2024/05/07 23:57
#ifndef MY_SKIP_LIST#define MY_SKIP_LIST#include <stdlib.h>#include <stdio.h>#include <limits.h>typedef int DataType;#define MAX_LEVEL 8struct DataNode;typedef struct NodeLevel{    struct DataNode * forward;    unsigned span;}NodeLevel,*PNodeLevel;/**data node which stores data with DataType*/typedef struct DataNode{//    int (*compare)(DataType val1,DataType val2);    DataType value;    unsigned level_size;    NodeLevel level[];}DataNode,*PDataNode;/**skip list struct*/typedef struct SkipList{    unsigned level;    unsigned size;    PDataNode header;}SkipList,*PSkipList;/** *get rand level for data node created */unsigned rand_level();/** *initialize an empty skiplist */PSkipList skiplist_init();/** *destory a skip list 'sl',and free the memory occupied. */void destory_skiplist(PSkipList *sl);/** *make a new skip list node which stores 'val', *returns a pointer to the data node newly made */PDataNode make_node(DataType val,unsigned level);/** *delete a data node with data 'val' from skip list 'sl', *returns a pointer of DataNode deleted, *if DataNode with data 'val' does not exist,return NULL *note:memory occupied by 'val' not freed */PDataNode del(PSkipList sl,DataType val);/** *add a data node with data 'val' from skip list 'sl', *returns a pointer of DataNode added, *note:memory occupied by 'val' not freed */PDataNode add(PSkipList sl,DataType val);/** *find 'val' in skiplist 'sl',if founed,return the pointer of node with value 'val' *if not return NULL */PDataNode find(PSkipList sl,DataType val);/** *free the memory occupied by 'node' */void free_node(PDataNode node);void print_skiplist(PSkipList sl);void print_level(PSkipList sl, int i);#endif // MY_SKIP_LIST
#include "skiplist.h"unsigned rand_level(){    int level = 1;    while(rand()%2 && level <= MAX_LEVEL)        level++;    return level;}PDataNode make_node(DataType val,unsigned level){    PDataNode node = (PDataNode)malloc(sizeof(DataNode) + sizeof(NodeLevel)*level);    if(node == NULL)        return NULL;    node->value = val;    node->level_size = level;    int i = 0;    for(i=0; i<level; i++)    {        node->level[i].forward = NULL;        node->level[i].span = 0;    }    return node;}void free_node(PDataNode node){    if(NULL == node)        return;    free(node);}PSkipList skiplist_init(){    PSkipList sl = NULL;    sl = (PSkipList)malloc(sizeof(SkipList));    sl->level = 1;    sl->size = 0;    PDataNode header = make_node(INT_MIN,MAX_LEVEL);    if(header == NULL)    {        free(sl);        return NULL;    }    sl->header = header;    return sl;}void destory_skiplist(PSkipList *sl){    if(*sl == NULL) return;    PDataNode pNode = (*sl)->header->level[0].forward;    PDataNode next = NULL;    while(pNode)    {        next = pNode->level[0].forward;        free_node(pNode);        pNode = next;    }    pNode = NULL;    next = NULL;    free_node((*sl)->header);    (*sl)->header = NULL;    free(*sl);    (*sl) = NULL;    return;}PDataNode del(PSkipList sl,DataType val){    if(sl == NULL) return NULL;    PDataNode del_node = NULL;    PNodeLevel update[MAX_LEVEL];    int i = MAX_LEVEL - 1;    PDataNode cur,pre;    pre = sl->header;    cur = pre;    while(i >= 0)    {        cur = pre->level[i].forward;        while(cur != NULL && cur->value < val)        {            pre = cur;            cur = cur->level[i].forward;        }        if(cur != NULL && cur->value == val)        {            del_node = cur;        }        update[i] = &(pre->level[i]);        i--;    }    if(del_node == NULL)        return NULL;    i = MAX_LEVEL - 1;    while(i >= 0)    {        if(update[i]->forward == NULL)        {            i--;            continue;        }        else if(update[i]->forward->value > val)        {            update[i]->span--;            i--;        }        else        {            update[i]->forward = del_node->level[i].forward;            if(del_node->level[i].forward == NULL)                update[i]->span = 0;            else                update[i]->span += del_node->level[i].span - 1;            i--;        }    }    sl->size--;    return del_node;}PDataNode add(PSkipList sl,DataType val){    if(sl == NULL) return NULL;    unsigned node_level = rand_level();    PDataNode pNode = make_node(val,node_level);    printf("Level:%d   value:%d\n",node_level,val);    if(pNode == NULL) return NULL;    PNodeLevel update[MAX_LEVEL];    //查找插入位置的遍历路径上处于第i层的节点在链表中的排位,头节点为rank[MAX_LEVEL-1]=0    //查找从最高层开始且头节点在链表中是第一个,所以rank[MAX_LEVEL-1]=0    unsigned rank[MAX_LEVEL] = {0};    int i =  MAX_LEVEL-1;    PDataNode cur,pre;    pre = sl->header;    cur = pre;    while(i >= 0)    {        rank[i] = (i == MAX_LEVEL-1 ? 0 : rank[i+1]);        cur = pre->level[i].forward;        while(cur && cur->value < val)        {            rank[i] += pre->level[i].span;            pre = cur;            cur = cur->level[i].forward;        }        if(cur && cur->value == val)            return NULL;        update[i] = &(pre->level[i]);        i--;    }    i = MAX_LEVEL-1;    for(;i >=0; i--)    {        if(update[i]->forward == NULL && i > node_level-1)        {            continue;        }        else if(update[i]->forward == NULL && i <= node_level-1)        {            update[i]->forward = pNode;            //节点的插入位置一定是在查找路基上第0层节点的后面一个            //rank[0] - rank[i]得到的是查找路径上要更新的第层节点距离第0层节点的距离跨度,            //这个跨度+1就得到了更新路劲上第i层节点到插入节点的跨度            update[i]->span = (rank[0] - rank[i]) + 1;        }        else if(update[i]->forward && i > node_level-1)        {            update[i]->span++;        }        else        {            pNode->level[i].forward = update[i]->forward;            //pNode->level[i].span = (update[i]->span + 1) - ((rank[0] - rank[i]) + 1);            pNode->level[i].span = update[i]->span - (rank[0] - rank[i]);            update[i]->forward = pNode;            update[i]->span = (rank[0] - rank[i]) + 1;        }    }    sl->size++;    return pNode;}PDataNode find(PSkipList sl,DataType val){    if(sl == NULL) return NULL;    PDataNode pre  = sl->header;    PDataNode cur = pre;    int i =  MAX_LEVEL-1;    unsigned rank[MAX_LEVEL-1] = {0};    while(i >= 0)    {        rank[i] = (i == MAX_LEVEL-1 ? 0 : rank[i+1]);        cur = pre->level[i].forward;        while(cur != NULL && cur->value < val)        {            rank[i] += pre->level[i].span;            pre = cur;            cur = cur->level[i].forward;        }        if(cur != NULL && cur->value == val)        {            printf("val=%d,rank:%u\n",val,rank[i]+1);            return cur;        }        i--;    }    return NULL;}void print_level(PSkipList sl, int i){    PDataNode pNode = sl->header;    printf("level  %d    ",i);    while(pNode)    {        printf("%d",pNode->value);        int num = pNode->level[i].span;        while(num > 0)        {            printf("-");            num--;        }        pNode = pNode->level[i].forward;    }    printf("\n");}void print_skiplist(PSkipList sl){    if(sl == NULL)    {        printf("Null list");        return ;    }    int i = MAX_LEVEL - 1;    while(i >= 0)    {        print_level(sl,i);        i--;    }}

#include <stdio.h>#include <stdlib.h>#include "skiplist.h"int main(){    PSkipList sl = skiplist_init();    DataType vals[] = {1,3,5,7,9,2,4,6,8,10,11,15,12,18,21,31,56,100,94,68,60,88,66};    unsigned val_size = sizeof(vals)/sizeof(vals[0]);    printf("value number = %u\n",val_size);    unsigned i = 0;    for(;i < val_size; i++)    {        add(sl,vals[i]);    }    print_skiplist(sl);    find(sl,31);    find(sl,100);    find(sl,66);    PDataNode del_node = del(sl,31);    free_node(del_node);    print_skiplist(sl);    del_node = del(sl,88);    free_node(del_node);    print_skiplist(sl);    del_node = del(sl,21);    free_node(del_node);    print_skiplist(sl);    del_node = del(sl,6);    free_node(del_node);    print_skiplist(sl);    del_node = del(sl,94);    free_node(del_node);    print_skiplist(sl);    del_node = del(sl,60);    free_node(del_node);    print_skiplist(sl);    del_node = del(sl,68);    free_node(del_node);    print_skiplist(sl);    del_node = del(sl,100);    free_node(del_node);    print_skiplist(sl);    del_node = del(sl,1);    free_node(del_node);    print_skiplist(sl);    del_node = NULL;    destory_skiplist(&sl);    print_skiplist(sl);    return 0;}


0 0
原创粉丝点击