skip list跳表C语言代码。

本文详细介绍了跳表的数据结构及其实现过程,包括插入、查找、删除等操作,并分享了在实现过程中遇到的问题和解决方案,特别强调了调试的困难与方法。

skip list(跳表)介绍文章可以看下面的文章

http://kenby.iteye.com/blog/1187303


跳表最有意思的想法应该是选择插入层数, random_level。

在写代码时候我出现了不少错误,了解跳表的设计思想后,写了一上午基本写好了,bug不断,调试花了一下午都没搞定,第二天才调试通过。

有莫名的断错误,后来发现分配内存少分配了一点,导致越界写,程序运行一段时间后出现段错误。


链表和树等数据结构的调试比较麻烦,执行时debug的难度比较大,通过看代码和打印数据慢慢找出写错的地方,总的来说写程序时间少,debug的时间多。


代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define SKIP_LIST_INIT_LEVEL  5

struct list_node_s;
struct list_s;
typedef struct list_node_s list_node_t;
typedef struct list_s list_t;

struct list_node_s {
	int key;
	void *value;
	int high;
	struct list_node_s **forward;
};

struct list_s {
	int level;
	struct list_node_s *header;
};


int random_level();
list_t *new_list(int init_level);
list_node_t *new_list_node(int high);
void *find(list_t *l, int key);
void insert(list_t *l, int key, void *value);
void *delete_node(list_t *l, int key);
void destroy(list_t *l);

int random_level()
{
	int k = 0;
//	srand(time(NULL));
	while (rand() % 2) {
		k++;
	}

	return k;
}

list_t *new_list(int init_level) 
{
	list_t *l;
	l = malloc(sizeof(list_t));
	l->header = new_list_node(init_level);
	l->level = 0;
	l->header->key = -1;
	return l;
}

list_node_t *new_list_node(int high) 
{
	int i;
	list_node_t *n;
	n = malloc(sizeof(list_node_t));
	n->forward = malloc(high *sizeof(void *));
	n->high = high;
	
	for (i = 0; i < high; i++) {
		n->forward[i] = NULL;
	}
	
	return n;
}

void destroy(list_t *l)
{
	list_node_t *n, *next;
	n = l->header;
	while (n) {
		next = n->forward[0];
		free(n->forward);
		free(n);
		n = next;
	}
	free(l);
}

void *find(list_t *l, int key)
{
	int k = l->level;
	list_node_t *n = l->header;
	
	while (n && k >= 0) {
		while(n->forward[k] && n->forward[k]->key <= key) {
			n = n->forward[k];
		}
		
		if (n->key == key) {
			return n->value;
		}
		k--;
	}

	return NULL;
}

void insert(list_t *l, int key, void *value)
{
	int insert_level;
	int k;
	size_t size;
	list_node_t *p, *q, *n;
	list_node_t **update;
	
	k = l->level;
	size = sizeof(void *) * (k + 1);
	update = malloc(size);
	p = q = l->header;

	while (q && k >= 0) {
		while (q->key < key) {
			p = q;
			if (q->forward[k]) {
				q = q->forward[k];
			}
			else {
				break;
			}
		}
		q = update[k] = p;
		//	printf("level:%d->%d ",k, p->key);
		k--;
	}

	insert_level = random_level();
	if (insert_level > l->level ) {

		k = l->level++;
		insert_level = l->level;
		n = new_list_node(insert_level + 1);
		n->key = key;
		n->value = value;
		if (insert_level >= l->header->high) {
			list_node_t **l1, **l2;
			l1 = malloc(sizeof(void *) * (insert_level + 1));
			l2 = l->header->forward;
			memcpy(l1, l2, sizeof(void *) * insert_level);
			l1[insert_level] = NULL;
			l->header->forward = l1;
			free(l2);
			l->header->high++;
			l->header->forward[insert_level] = n;
		}
		else {
			l->header->forward[insert_level] = n;
		}

	}
	else {
		k = insert_level;
		n = new_list_node(k + 1);
		n->value = value;
		n->key = key;
	}
//	printf("key: %d update: ", key);
	
	while (k >= 0) {
		p = update[k];
//		printf("%d ", p->key);
		q = p->forward[k];
		p->forward[k] = n;
		n->forward[k] = q;
		k--;
	}
//	printf("\n");
	free(update);
}

void *delete(list_t *l, int key) 
{
	int k = l->level;
	list_node_t *p, *q, *n;
	p = q = l->header;
	n = NULL;
	list_node_t **update;
	
	update = malloc(sizeof(void *) * (k + 1));
	
	while (q && k >= 0) {
		while (q->key < key) {
			p = q;
			if (q->forward[k]) {
				q = q->forward[k];
			}
			else {
				break;
			}
		}
		
		q = update[k] = p;
	
		k--;
	}

	if (update[0]->forward[0] && update[0]->forward[0]->key == key) {
		n = update[0]->forward[0];
	}
	else {
		free(update);
		return NULL;
	}
	
	k = n->high - 1;
	while (k >= 0) {
		p = update[k];
		p->forward[k] = n->forward[k];
		k--;
	}

	free(update);
	return n->value;
}



void show_list(list_t *l) 
{
	int k = l->level;
	list_node_t *n;
	n = l->header;
	while (k >= 0) {
		n = l->header;
		while (n) {
			printf("%d ", n->key);
			n = n->forward[k];
		}
		printf("\n");
		k--;
	}
}

int main(int argc, char *argv[]) 
{
	int k, i;
	list_t *l;
	void *ptr = &k;
	l = new_list(10);
	k = atoi(argv[1]);
	
	srand(time(NULL));
	i = k;

	printf("---------------\n");
	while (i > 0) {
		int key;
		key = rand() % k;
		insert(l, key, ptr);
		//	show_list(l);
		i--;
	}
	i = k ;
	show_list(l);
	while (i > 0) {
		int key;
		void *p;
		key = rand() % k;
		p = find(l, key);
		if (p == NULL) {
			printf("key %d not found\n", key);
		}
		else {
			delete(l, key);
			printf("key %d found\n", key);
		}
		i--;
	}
	printf("\n--------------\n");
	show_list(l);
	destroy(l);
	return 0;
}



跳表是一种概率性数据结构,插入、删除、查找元素的时间复杂度与红黑树处于相同量级,均为 O(logn),在工业中应用较为广泛 [^3]。以下是一个简单的 C 语言实现跳表的示例: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define MAX_LEVEL 16 #define PROBABILITY 0.5 // 定义跳表节点结构 typedef struct Node { int key; struct Node **forward; } Node; // 定义跳表结构 typedef struct SkipList { Node *head; int level; } SkipList; // 创建新节点 Node* createNode(int key, int level) { Node *node = (Node*)malloc(sizeof(Node)); node->key = key; node->forward = (Node**)malloc((level + 1) * sizeof(Node*)); for (int i = 0; i <= level; i++) { node->forward[i] = NULL; } return node; } // 创建跳表 SkipList* createSkipList() { SkipList *list = (SkipList*)malloc(sizeof(SkipList)); list->head = createNode(-1, MAX_LEVEL); list->level = 0; return list; } // 随机生成层级 int randomLevel() { int level = 0; while ((double)rand() / RAND_MAX < PROBABILITY && level < MAX_LEVEL) { level++; } return level; } // 插入操作 void insert(SkipList *list, int key) { Node *update[MAX_LEVEL + 1]; Node *current = list->head; for (int i = list->level; i >= 0; i--) { while (current->forward[i] != NULL && current->forward[i]->key < key) { current = current->forward[i]; } update[i] = current; } current = current->forward[0]; if (current == NULL || current->key != key) { int level = randomLevel(); if (level > list->level) { for (int i = list->level + 1; i <= level; i++) { update[i] = list->head; } list->level = level; } Node *newNode = createNode(key, level); for (int i = 0; i <= level; i++) { newNode->forward[i] = update[i]->forward[i]; update[i]->forward[i] = newNode; } } } // 查找操作 int search(SkipList *list, int key) { Node *current = list->head; for (int i = list->level; i >= 0; i--) { while (current->forward[i] != NULL && current->forward[i]->key < key) { current = current->forward[i]; } } current = current->forward[0]; if (current != NULL && current->key == key) { return 1; } return 0; } // 删除操作 void delete(SkipList *list, int key) { Node *update[MAX_LEVEL + 1]; Node *current = list->head; for (int i = list->level; i >= 0; i--) { while (current->forward[i] != NULL && current->forward[i]->key < key) { current = current->forward[i]; } update[i] = current; } current = current->forward[0]; if (current != NULL && current->key == key) { for (int i = 0; i <= list->level; i++) { if (update[i]->forward[i] != current) { break; } update[i]->forward[i] = current->forward[i]; } free(current->forward); free(current); while (list->level > 0 && list->head->forward[list->level] == NULL) { list->level--; } } } // 打印跳表 void printSkipList(SkipList *list) { for (int i = list->level; i >= 0; i--) { Node *current = list->head->forward[i]; printf("Level %d: ", i); while (current != NULL) { printf("%d -> ", current->key); current = current->forward[i]; } printf("NULL\n"); } } // 释放跳表内存 void freeSkipList(SkipList *list) { Node *current = list->head; while (current != NULL) { Node *temp = current; current = current->forward[0]; free(temp->forward); free(temp); } free(list); } int main() { srand(time(NULL)); SkipList *list = createSkipList(); insert(list, 3); insert(list, 6); insert(list, 7); insert(list, 9); insert(list, 12); insert(list, 19); insert(list, 17); insert(list, 26); insert(list, 21); insert(list, 25); printSkipList(list); printf("Search 19: %s\n", search(list, 19) ? "Found" : "Not Found"); delete(list, 19); printf("After deleting 19:\n"); printSkipList(list); freeSkipList(list); return 0; } ``` ### 代码解释 - **节点结构**:`Node` 结构体包含一个键 `key` 和一个指向前驱节点的指针数组 `forward`,用于存储不同层级的链接。 - **跳表结构**:`SkipList` 结构体包含一个头节点 `head` 和当前的最大层级 `level`。 - **随机层级生成**:`randomLevel` 函数通过随机数和概率 `PROBABILITY` 来决定新节点的层级。 - **插入操作**:`insert` 函数首先找到插入位置,然后根据随机生成的层级更新跳表。 - **查找操作**:`search` 函数从最高层级开始,逐层向下查找目标键。 - **删除操作**:`delete` 函数找到要删除的节点,然后更新跳表的链接。 ### 复杂度分析 - **时间复杂度**:插入、删除和查找操作的平均时间复杂度为 O(logn)。 - **空间复杂度**:平均空间复杂度为 O(n)。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值