从搜索的资料来看,
重复的关键字让人感觉有一点不安,逻辑上的和空间消耗上的,于是找一些其他相关是否有改进的。
deterministic skip list, 2-3-4* x->forword[i]->key 的x->forword[i]指向最底层数据实体。
#include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX_LEVEL 32 typedef struct sl_node{ int key; int val; int level; struct sl_node **fwd; }sl_node_t; typedef struct { int level; sl_node_t *header; }sl_t; int node_level(void) { int lvl = 1; while( rand() < RAND_MAX/2 && lvl < MAX_LEVEL){ ++lvl; } return lvl; } static sl_node_t *node_alloc(int key, int val, int level) { sl_node_t *x = malloc(sizeof(*x)); x->key = key; x->val = val; x->level = level; x->fwd = malloc(level * sizeof(x->fwd[0])); memset(x->fwd, 0, level * sizeof(x->fwd[0])); return x; } static void node_free(sl_node_t *x) { free(x->fwd); free(x); } void sl_stats(sl_t *sl) { sl_node_t *x = sl->header->fwd[0]; int lvl[MAX_LEVEL] = {0}; int i, cnt = 0; for(; x; x = x->fwd[0]){ if(0 <= x->level && x->level < MAX_LEVEL){ lvl[x->level]++; }else{ printf("bad (%d,%d):%d ", x->key, x->val, x->level); } ++cnt; } printf("\nlevel:count "); for(i = 0; i < sizeof(lvl)/sizeof(lvl[0]); ++i){ if(lvl[i]){ printf("%d:%d ", i, lvl[i]); } } printf(" ==cnt %d\n", cnt); } sl_t* sl_create(void) { sl_t *x = malloc(sizeof(*x)); x->level = 0; x->header = node_alloc(0, 0, MAX_LEVEL); return x; } int sl_find(sl_t *sl, int key, int *val) { int i; sl_node_t *x = sl->header; for(i = sl->level-1; i >= 0; --i){ while(x->fwd[i] && x->fwd[i]->key < key){ x = x->fwd[i]; } } /*now at bottom: x->fwd[0] == NIL or x->fwd[0]->key >= key*/ x = x->fwd[0]; if(x && x->key == key){ *val = x->val; return 1; }else{ return 0; } } int sl_insert(sl_t *sl, int key, int val) { int i, lvl; sl_node_t *slice[MAX_LEVEL] = {0}; sl_node_t *x = sl->header; for(i = sl->level-1; i >= 0; --i){ while(x->fwd[i] && x->fwd[i]->key < key){ x = x->fwd[i]; } slice[i] = x; } x = x->fwd[0]; if(x && x->key == key){ x->val = val; return 0; }else{ lvl = node_level(); if(lvl > sl->level){ for(i = sl->level; i < lvl; ++i){ slice[i] = sl->header; } sl->level = lvl; } x = node_alloc(key, val, lvl); for(i = 0; i < lvl; ++i){ x->fwd[i] = slice[i]->fwd[i]; slice[i]->fwd[i] = x; } return 1; } } int sl_delete(sl_t *sl, int key, int *val) { int i; sl_node_t *slice[MAX_LEVEL] = {0}; sl_node_t *x = sl->header; for(i = sl->level-1; i >= 0; --i){ while(x->fwd[i] && x->fwd[i]->key < key){ x = x->fwd[i]; } slice[i] = x; } x = x->fwd[0]; if(x && x->key == key){ for(i = 0; i < sl->level; ++i){ if(slice[i]->fwd[i] != x){break;} slice[i]->fwd[i] = x->fwd[i]; } *val = x->val; node_free(x); while(sl->level > 0 && !sl->header->fwd[sl->level-1]){ sl->level--; } return 1; } return 0; } #if defined(TEST_SL) int main(int ac, char **av) { sl_t *sl = sl_create(); int i; int n = ac > 1 ? atoi(av[1]) : 16; int val = -1; for(i = 0; i < n; ++i){ sl_insert(sl, i, i*i); val = -1; sl_find(sl, i-1, &val); if(val != (i-1)*(i-1)){ printf("err find key %d val %d\n", i-1, val); } } sl_stats(sl); for(i = 0; i < n; ++i){ val = -1; sl_delete(sl, i, &val); if(val != i*i){ printf("del key %d val %d\n", i, val); } } return 0; } #endif