从搜索的资料来看,
重复的关键字让人感觉有一点不安,逻辑上的和空间消耗上的,于是找一些其他相关是否有改进的。
deterministic skip list, 2-3-4tree的翻版,top-down方式维护平衡,感觉还是走的老路,且连续三者取中来提升,
局部性不好,对concurrent不友好。
又重新仔细读了一遍Pugh原文,
"A level i node has i forward pointers..."
看到x := makeNode(lvl, newValue);
突然领悟到匠心独运:
* 每个接口创建后level数组就固定了,不需要realloc。
* 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