You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

297 lines
7.7 KiB

#include <stdio.h>
#include "skiplist.h"
struct skiplist_t{
skiplist_node_t* header;
skiplist_size_t size;
int level;
skiplist_probability_t probability;
skiplist_cmp cmp;
};
#define SKIPLIST_LEVEL_MAX 32
struct skiplist_level_t{
skiplist_node_t* next;
};
struct skiplist_node_t{
void* data;
skiplist_node_t* prev;
skiplist_level_t lev[];
};
static inline skiplist_node_t* __skiplist_node_create(int level){
return (skiplist_node_t*)SKIPLIST_ALLOC_MEM(sizeof(skiplist_node_t) + sizeof(skiplist_level_t) * level);
}
static inline void __skiplist_node_destroy(skiplist_node_t* node){
SKIPLIST_FREE_MEM(node);
}
static inline int __skiplist_random_level(skiplist_t* sl){
int level = 1;
while(SKIPLIST_RAND() >= (RAND_MAX * sl->probability)){
++ level;
}
return (level > SKIPLIST_LEVEL_MAX ? SKIPLIST_LEVEL_MAX : level);
}
static inline int
__skiplist_create(
skiplist_t** sl,
skiplist_probability_t probability,
skiplist_cmp cmp
){
skiplist_t* tsl = (skiplist_t*)SKIPLIST_ALLOC_MEM(sizeof(skiplist_t));
if(tsl == NULL){
*sl = tsl;
return SKIPLISTERR_POINTR;
}
if((tsl->header = __skiplist_node_create(SKIPLIST_LEVEL_MAX)) == NULL){
*sl = NULL;
SKIPLIST_FREE_MEM(tsl);
return SKIPLISTERR_POINTR;
}
tsl->header->prev = tsl->header;
int i = 0;
for(;i < SKIPLIST_LEVEL_MAX; ++i){
tsl->header->lev[i].next = tsl->header;
}
tsl->size = 0;
tsl->level = 1;
tsl->probability = probability;
tsl->cmp = cmp;
*sl = tsl;
return SKIPLISTOK;
}
static inline int
__skiplist_insert(
skiplist_t* sl,
void* key,
void* data
){
skiplist_node_t* level_prev[SKIPLIST_LEVEL_MAX];
skiplist_node_t *cur = sl->header,*end = sl->header;
skiplist_node_t* node;
int i = sl->level - 1,level;
for(;i >= 0; -- i){
for(;cur->lev[i].next != end && sl->cmp(key,cur->lev[i].next->data) > 0;cur = cur->lev[i].next);
level_prev[i] = cur;
}
if(cur->lev[0].next != end && sl->cmp(key,cur->lev[0].next->data) == 0){
return SKIPLISTERR_REEXIST;
}
level = __skiplist_random_level(sl);
if((node = __skiplist_node_create(level)) == NULL){
return SKIPLISTERR_POINTR;
}
node->data = data;
if(level > sl->level){
for(i = sl->level;i < level; ++ i){
level_prev[i] = sl->header;
}
sl->level = level;
}
for(i = 0;i < level; ++ i){
node->lev[i].next = level_prev[i]->lev[i].next;
level_prev[i]->lev[i].next = node;
}
node->prev = level_prev[0];
node->lev[0].next->prev = node;
++ sl->size;
return SKIPLISTOK;
}
static inline int
__skiplist_erase(
skiplist_t* sl,
void* key,
void** retdata
){
skiplist_node_t* level_prev[SKIPLIST_LEVEL_MAX];
skiplist_node_t *cur = sl->header,*end = sl->header;
skiplist_node_t* node;
int i = sl->level - 1;
for(;i >= 0; -- i){
for(;cur->lev[i].next != end && sl->cmp(key,cur->lev[i].next->data) > 0;cur = cur->lev[i].next);
level_prev[i] = cur;
}
if(cur->lev[0].next == end || sl->cmp(key,cur->lev[0].next->data) < 0){
return SKIPLISTERR_NOEXIST;
}
cur = cur->lev[0].next;
node = cur;
for(i = 0;i < sl->level; ++i){
if(level_prev[i]->lev[i].next == node){
level_prev[i]->lev[i].next = node->lev[i].next;
}
}
node->lev[0].next->prev = node->prev;
for(;sl->level > 1 && sl->header->lev[sl->level - 1].next == end; -- sl->level);
if(retdata != NULL){
*retdata = node->data;
}
__skiplist_node_destroy(node);
-- sl->size;
return SKIPLISTOK;
}
static inline int
__skiplist_exist(
skiplist_t* sl,
void* key,
void** retdata
){
skiplist_node_t *cur = sl->header,*end = sl->header;
int i = sl->level - 1;
for(;i >= 0; -- i){
for(;cur->lev[i].next != end && sl->cmp(key,cur->lev[i].next->data) > 0;cur = cur->lev[i].next);
}
if(cur->lev[0].next != end && sl->cmp(key,cur->lev[0].next->data) == 0){
if(retdata != NULL){
*retdata = cur->lev[0].next->data;
}
return SKIPLISTOK_EXIST;
}
return SKIPLISTERR_NOEXIST;
}
static inline int
__skiplist_update(
skiplist_t* sl,
void* oldkey,
void* newkey,
void* newdata,
void** retdata
){
skiplist_node_t* level_prev[SKIPLIST_LEVEL_MAX];
skiplist_node_t *cur = sl->header,*node,*end = sl->header;
int i = sl->level - 1;
for(;i >= 0; -- i){
for(;cur->lev[i].next != end && sl->cmp(oldkey,cur->lev[i].next->data) > 0;cur = cur->lev[i].next);
level_prev[i] = cur;
}
if(cur->lev[0].next != end && sl->cmp(oldkey,cur->lev[0].next->data) == 0){
cur = cur->lev[0].next;
if((cur->prev != end && sl->cmp(newkey,cur->prev->data) == 0) ||
(cur->lev[0].next != end && sl->cmp(newkey,cur->lev[0].next->data) == 0)){
return SKIPLISTERR_REEXIST;
}
if(sl->cmp(newkey,cur->data) == 0){
if(retdata != NULL){
*retdata = cur->data;
}
cur->data = newdata;
}
else{
node = cur;
for(i = 0;i < sl->level; ++ i){
if(level_prev[i]->lev[i].next == node){
level_prev[i]->lev[i].next = node->lev[i].next;
}
}
node->lev[0].next->prev = node->prev;
for(;sl->level > 1 && sl->header->lev[sl->level - 1].next == end; -- sl->level);
if(retdata != NULL){
*retdata = node->data;
}
__skiplist_node_destroy(node);
-- sl->size;
return __skiplist_insert(sl,newkey,newdata);
}
return SKIPLISTOK;
}
return SKIPLISTERR_NOEXIST;
}
int skiplist_create(skiplist_t** sl,skiplist_probability_t probability,skiplist_cmp cmp){
if(sl == NULL || probability <= 1e-6 || probability - 1 >= 1e-6 || cmp == NULL){
return SKIPLISTERR_PARAM;
}
return __skiplist_create(sl,probability,cmp);
}
int skiplist_size(skiplist_t* sl,skiplist_size_t* size){
if(sl == NULL || size == NULL){
*size = 0;
return SKIPLISTERR_PARAM;
}
*size = sl->size;
return SKIPLISTOK;
}
int skiplist_getcmp(skiplist_t* sl,skiplist_cmp* cmp){
if(sl == NULL || cmp == NULL){
return SKIPLISTERR_PARAM;
}
*cmp = sl->cmp;
return SKIPLISTOK;
}
int skiplist_insert(skiplist_t* sl,void* key,void* data){
if(sl == NULL || key == NULL || data == NULL){
return SKIPLISTERR_PARAM;
}
return __skiplist_insert(sl,key,data);
}
int skiplist_erase(skiplist_t* sl,void* key,void** retdata){
if(sl == NULL || key == NULL){
return SKIPLISTERR_PARAM;
}
return __skiplist_erase(sl,key,retdata);
}
int skiplist_exist(skiplist_t* sl,void* key,void** retdata){
if(sl == NULL || key == NULL){
return SKIPLISTERR_PARAM;
}
return __skiplist_exist(sl,key,retdata);
}
int skiplist_update(skiplist_t* sl,void* oldkey,void* newkey,void* newdata,void** retdata){
if(sl == NULL || oldkey == NULL || newkey == NULL || newdata == NULL){
return SKIPLISTERR_PARAM;
}
return __skiplist_update(sl,oldkey,newkey,newdata,retdata);
}
int skiplist_destroy(skiplist_t** sl){
if(sl == NULL || *sl == NULL){
return SKIPLISTERR_PARAM;
}
skiplist_node_t *cur = (*sl)->header,*tmp,*end = (*sl)->header;
for( ;cur != end; cur = tmp){
tmp = cur->lev[0].next;
__skiplist_node_destroy(cur);
}
SKIPLIST_FREE_MEM(*sl);
*sl = NULL;
return SKIPLISTOK;
}
int skiplist_begin(skiplist_t* sl,skiplist_iterator_t* it){
int ret = SKIPLISTERR_PARAM;
if(sl == NULL || it == NULL){
return ret;
}
if((ret = skiplist_iterator_create(it)) == SKIPLISTOK){
*it = sl->header->lev[0].next;
}
return ret;
}
int skiplist_end(skiplist_t* sl,skiplist_iterator_t* it){
int ret = SKIPLISTERR_PARAM;
if(sl == NULL || it == NULL){
return ret;
}
if((ret = skiplist_iterator_create(it)) == SKIPLISTOK){
*it = sl->header;
}
return ret;
}
int skiplist_iterator_create(skiplist_iterator_t* it){
return SKIPLISTOK;
}
int skiplist_iterator_equal(skiplist_iterator_t* it1,skiplist_iterator_t* it2){
return ((*it1) == (*it2));
}
void skiplist_iterator_assign(skiplist_iterator_t* dit,const skiplist_iterator_t* sit){
(*dit) = (*sit);
}
const void* skiplist_iterator_value(skiplist_iterator_t* it){
return (*it)->data;
}
void skiplist_iterator_next(skiplist_iterator_t* it){
(*it) = (*it)->lev[0].next;
}
void skiplist_iterator_prev(skiplist_iterator_t* it){
(*it) = (*it)->prev;
}
void skiplist_iterator_destroy(skiplist_iterator_t* it){
;
}