Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rewrite skiplist.c, a few bug fixes #534

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions c-cpp/17_skiplist/SkipList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,10 +354,8 @@ int GetRandom()
int CSkipList::RandomLevel()
{
int level = 1;
for(int i=1; i<MAX_LEVEL; ++i){
if(1 == (GetRandom()%3)){
level++;
}
for(int i=1; i<MAX_LEVEL && GetRandom()%3; ++i){
level++;
}
return level;
}
284 changes: 115 additions & 169 deletions c-cpp/17_skiplist/skiplist.c
Original file line number Diff line number Diff line change
@@ -1,214 +1,160 @@
// https://www.youtube.com/watch?v=2g9OSRKJuzM&t=17s
// note: 层数从0开始算,非空跳表的最低level是0,空跳表的level是-1。
// note: 因为randomization的关系,跳表允许的最大层数需要事先设定,
// 当n足够大时,跳表的层数(即节点索引的最大层数)将约等于log2(n)。
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <time.h>

// https://www.youtube.com/watch?v=2g9OSRKJuzM&t=17s

#define MAX_LEVEL 15
#define SKIPLIST_P 0.5
#define INVALID_KEY -1

struct node {
int val;
int max_level;
struct node *forward[MAX_LEVEL];
};
typedef int ktype;

struct skip_list {
struct node head;
int max_level;
int max_level_nodes;
};

void node_init(struct node* node)
typedef struct node_
{
memset(node, 0, sizeof(struct node));
}
// dtype data;
ktype key;
int level;
struct node_ **forward;
} node;

void skip_list_init(struct skip_list* sl)
typedef struct
{
node_init(&sl->head);
sl->max_level = 0;
sl->max_level_nodes = 0;
}
node *head;
int level; // 跳表的当前层数,允许的最大层数是head->level
int nodes;
} skip_list;

void random_init()
skip_list *make_skip_list(int max_level)
{
static bool done = false;

if (done)
return;

srandom(time(NULL));
done = true;
skip_list *sl = (skip_list *)malloc(sizeof(skip_list));
sl->level = -1;
sl->head = (node *)malloc(sizeof(node));
sl->head->key = INVALID_KEY;
sl->head->level = max_level;
sl->head->forward = (node **)malloc(sizeof(node *) * max_level); // 注意头节点的指针数量不等于sl的max_level
memset(sl->head->forward, 0, sizeof(node *) * max_level);
return sl;
}

int random_level(void)
int random_level(int max_level)
{
int i, level = 1;

random_init();

for (i = 1; i < MAX_LEVEL; i++)
if (random() % 2 == 1)
level++;

return level;
static const int threshold = SKIPLIST_P * RAND_MAX;
int level = 0;
while (random() < threshold) //在0.5概率下循环平均执行次数趋于2,因此max_level的比较放外面会更快
level++;
return (level < max_level) ? level : max_level;
}

void random_level_test()
node *search(skip_list *sl, ktype key)
{
printf("random level %d\n", random_level());
printf("random level %d\n", random_level());
printf("random level %d\n", random_level());
printf("random level %d\n", random_level());
printf("random level %d\n", random_level());
}

void insert(struct skip_list *sl, int val)
{
int level = random_level();
struct node *update[MAX_LEVEL];
struct node *new, *p;
int i;

new = (struct node*)malloc(sizeof(struct node));
if (!new)
return;

new->max_level = level;
new->val = val;

for (int i = 0; i < MAX_LEVEL; i++)
update[i] = &sl->head;

p = &sl->head;
for (i = level - 1; i >= 0; i--) {
while(p->forward[i] && p->forward[i]->val < val)
p = p->forward[i];

update[i] = p;
node *cur = sl->head;
for (int i = sl->level; i >= 0; i--)
{
while (cur->forward[i] != NULL && cur->forward[i]->key <= key)
cur = cur->forward[i];
if (cur->key == key)
return cur;
}

for (i = 0; i < level; i++) {
new->forward[i] = update[i]->forward[i];
update[i]->forward[i] = new;
}

if (sl->max_level < level) {
sl->max_level = level;
sl->max_level_nodes = 1;
} else if (sl->max_level == level)
sl->max_level_nodes++;
return NULL;
}

struct node *find(struct skip_list* sl, int val)
node *insert(skip_list *sl, ktype key)
{
struct node *node = &sl->head;
int i;

for (i = sl->max_level - 1; i >= 0; i--) {
while (node->forward[i] && node->forward[i]->val < val)
node = node->forward[i];
}

if (node->forward[0] && node->forward[0]->val == val) {
return node->forward[0];
// 构造新节点
int level = random_level(sl->head->level);
if (level > sl->level)
sl->level = level;
node *new_node = (node *)malloc(sizeof(node));
new_node->key = key;
new_node->level = level;
new_node->forward = (node **)malloc(sizeof(node *) * level);
// 插入
node *cur = sl->head;
for (int i = sl->level; i >= 0; i--)
{
while (cur->forward[i] != NULL && cur->forward[i]->key <= key) //同样键值的情况插入到后面
cur = cur->forward[i];
if (level >= i)
{
new_node->forward[i] = cur->forward[i];
cur->forward[i] = new_node;
}
}
else
return NULL;
sl->nodes++;
return new_node;
}

void delete(struct skip_list* sl, int val)
void delete(skip_list *sl, ktype key)
{
struct node *update[MAX_LEVEL];
struct node *p;
int i;

p = &sl->head;

for (i = sl->max_level; i >= 0; i--) {
while (p->forward[i] && p->forward[i]->val < val)
p = p->forward[i];

update[i] = p;
}

if (p->forward[0] == NULL || p->forward[0]->val != val)
return;

if (p->forward[0]->max_level == sl->max_level)
sl->max_level_nodes--;

for (i = sl->max_level-1; i >= 0; i--) {
if (update[i]->forward[i] && update[i]->forward[i]->val == val)
update[i]->forward[i] = update[i]->forward[i]->forward[i];
node *cur = sl->head;
node *target = NULL;
for (int i = sl->level; i >= 0; i--)
{
while (cur->forward[i] != NULL && cur->forward[i]->key < key) //同样键值的情况删除最前面者
cur = cur->forward[i];
if (cur->forward[i] != NULL && cur->forward[i]->key == key) //删除该层的链接
{
target = cur->forward[i];
cur->forward[i] = target->forward[i];
}
}

// fixup max_level and max_level_nodes
if (sl->max_level_nodes == 0) {
//sl->max_level--;
p = &sl->head;
// skip (max_level - 1), direct test (max_level - 2)
// since no nodes on (max_level - 1)
for (i = sl->max_level - 2; i >= 0; i--) {
while (p->forward[i]) {
sl->max_level_nodes++;
p = p->forward[i];
}

if (sl->max_level_nodes) {
sl->max_level = i + 1;
break;
} else
sl->max_level = i;
if (target != NULL)
{
if (target->level == sl->level)
{
while (sl->head->forward[sl->level] == NULL)
sl->level--;
}
free(target->forward);
free(target);
sl->nodes--;
}
}


void print_sl(struct skip_list* sl)
void print_sl(skip_list *sl)
{
struct node *node;
int level;

printf("%d level skip list with %d nodes on top\n",
sl->max_level, sl->max_level_nodes);

for (level = sl->max_level - 1; level >= 0; level--) {
node = &sl->head;
printf("Level[%02d]:", level);
while (node->forward[level]) {
printf("%4d", node->forward[level]->val);
node = node->forward[level];
printf("%d level skip list with %d nodes\n", sl->level, sl->nodes);
for (int i = sl->level; i >= 0; i--)
{
node *cur = sl->head;
printf("Level[%02d]:", i);
while (cur->forward[i])
{
cur = cur->forward[i];
printf("%4d", cur->key);
}
printf("\n");
}
}

int main()
int main(int argc, char* argv[])
{
struct skip_list sl;
struct node *node = NULL;
int i;

skip_list_init(&sl);
print_sl(&sl);

for (i = 0; i < 10; i++)
insert(&sl, i);
print_sl(&sl);

node = find(&sl, 8);
if (node)
printf("find 8 in sl %d\n", node->val);
srandom(1689859321);
skip_list *sl = make_skip_list(15);
print_sl(sl);

ktype a[] = {4, 3, 6, 9, 7, 1, 2, 5, 8};
const int n = sizeof(a) / sizeof(ktype);
for (int i = 0; i < n; i++)
insert(sl, a[i]);
print_sl(sl);

node *cur = search(sl, 8);
if (cur)
printf("find 8 in sl: %d\n", cur->key);
else
printf("8 not in sl\n");

for (i = 0; i < 10; i++) {
delete(&sl, i);
print_sl(&sl);
for (int i = 0; i < n; i++)
{
delete(sl, a[i]);
printf("delete %d\n", a[i]);
print_sl(sl);
}

return 0;
}
}
11 changes: 4 additions & 7 deletions c-cpp/17_skiplist/skiplist_c/skiplist.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,8 @@ int skip_list_level(skiplist * list)
{
int i = 0;
int level = 1;
for (i = 1; i < list->head->max_level; i++)
{
if ((rand()%2) == 1)
{
level++;
}
}
for (i = 1; i < list->head->max_level && rand() % 2; i++)
level++;

return level;
}
Expand Down Expand Up @@ -152,6 +147,7 @@ int skip_list_insert(skiplist *list,int key,int value)
}

list->count++;
free(update);
return 0;
}

Expand Down Expand Up @@ -221,6 +217,7 @@ int skip_list_delete(skiplist * list, int key ,int *value)
return 3;/*未找到节点*/
}

free(update);
return 0 ;
}

Expand Down