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);
}