跳表的原理和实现

        redis中sort-set的底层是跳表。跳表是一种变形的链表。普通链表的查找删除的时间复杂度为O(n),但是使用跳表的期望值是log2(n),媲美AVL树。
跳表的节点思想:
跳表的节点,通过指针指向一个可动态开辟长度的数组,根据随机的数字来随机该节点的跳表level,每个level又是一个指针,指向该level的下一个节点,最终指向NULl。
跳表的插入思想:
每个跳表节点都有数组存放着level的指针,插入数据的时候,首先随机一个level给新要插入的数据。然后从头结点的对应level开始,模拟单链表进行查找,如果待插入值小于节点值,则进行纵向查找即减少level值。重复进行该操作,同时需要记录下每次链表指向的节点值,当level值为空或者没有查找到该元素,则返回失败,否则成功。链表的前后串联起来。
跳表的删除思想:
类似于插入操作,不同的是,找到元素则进行删除,没找到则返回失败。

参考博客:http://blog.csdn.net/linyu19872008/article/details/72403962
  http://blog.csdn.net/bluecll/article/details/37094991

  http://blog.51cto.com/flyingsnail/1020034

        代码实现:

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

#define MAX_LEVEL 8

struct Node
{
	int value;
	struct Node *next[1];
};
typedef struct SkipList
{
	int level;
	struct Node *head;
}SkipList;

Node *CreateNode(int level, int value)
{
	Node *node = (Node *)malloc(sizeof(Node) + level *sizeof(Node *));
	node->value = value;
	return node;
}
SkipList *Init()
{
	//SkipList *list = new SkipList();
	SkipList *list = (SkipList *)malloc(sizeof(SkipList));
	list->level = 0;
	list->head = CreateNode(MAX_LEVEL + 1, 0);
	for (int i = 0; i < MAX_LEVEL; i++)
	{
		list->head->next[i] = NULL;
	}
	return list;
}
int Random()
{
	int k = 1;
	while (rand() % 2)
	{
		k++;
	}
	return k > MAX_LEVEL ? MAX_LEVEL : k;
}
void Insert(SkipList *list, int value)
{
	Node *update[MAX_LEVEL];
	Node *p, *q = NULL;
	p = list->head;
	int k = list->level;

	//记录下value应该插入的每一层的位置
	for (int i = k - 1; i >= 0; --i)
	{
		while ((q = p->next[i]) && (q->value <= value))
		{
			if (q->value == value)
			{
				printf("error:insert error %d\n", value);
				return;
			}
			p = q;
		}
		update[i] = p;
	}

	//更新skiplist的level值
	k = Random();
	if (k > list->level)
	{
		for (int i = list->level; i < k; ++i)
		{
			update[i] = list->head;
		}
		list->level = k;
	}

	//进行申请节点,插入操作
	Node *node = CreateNode(k, value);
	printf("k: %d    level: %d\n", k, list->level);
	for (int i = 0; i < k; ++i)
	{
		node->next[i] = update[i]->next[i];
		update[i]->next[i] = node;
	}
}
void Delete(SkipList *list, int value)
{
	Node *update[MAX_LEVEL];
	Node *p, *q = NULL;
	p = list->head;
	int k = list->level;

	//一层一层的查找value值
	for (int i = k - 1; i >= 0; --i)
	{
		while ((q = p->next[i]) && q->value < value)
			p = q;
		update[i] = p;
	}
	
	//如果和最底层相等证明存在
	if (q && (q->value == value))
	{
		for (int i = 0; i < k; ++i)
		{
			if (update[i]->next[i] == q)
			{
				update[i]->next[i] = q->next[i];
			}
		}
		free(q);

		//重新维护跳表的level
		for (int i = list->level - 1; i >= 0; --i)
		{
			if (list->head->next[i] == NULL)
			{
				list->level--;
			}
		}
	}
}
//void Show(SkipList *sl)
//{
//	//从最高层开始打印  
//	Node *p, *q = NULL;
//
//	//从最高层开始搜  
//	int k = sl->level;
//	for (int i = k - 1; i >= 0; i--)
//	{
//		p = sl->head;
//		while (q = p->next[i])
//		{
//			printf("%d -> ", p->value);
//			p = q;
//		}
//		printf("\n");
//	}
//	printf("\n");
//}
void Show(SkipList *list)
{
	Node *p, *q = NULL;
	for (int i = list->level - 1; i >= 0; --i)
	{
		p = list->head;
		while (q = p->next[i])
		{
			printf("%d -> ", q->value);
			p = q;
		}
		printf("\n");
	}
	printf("\n");
}
int main()
{
	SkipList *list = Init();
	int ar[] = { 5, 7, 6, 4, 3, 9, 0, 1, 8 , 2 , 2};
	for (int i = 0; i < sizeof(ar)/sizeof(ar[0]); ++i)
	{
		Insert(list, ar[i]);
	}
	Show(list);
	Show(list);
	Delete(list, 8);
	Show(list);
}

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值