跳表(SkipList) -- 基于概率的平衡二叉树

从搜索的资料来看,

重复的关键字让人感觉有一点不安,逻辑上的和空间消耗上的,于是找一些其他相关是否有改进的。

deterministic skip list, 2-3-4
tree的翻版,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


你可能感兴趣的:(搜索)