跳跃表是对有序的链表增加上附加的前进链接,增加是以随机化的方式进行的,所以在列表中的查找可以快速的跳过部分列表。它的效率可以做到和平衡树相同的平均时间复杂度O(logN),其空间复杂度为O(N);
跳跃列表的算法有同平衡树一样的渐进的预期时间边界,并且更简单、更快速和使用更少的空间。
性质
1、有很多层结构(链表)组成
2、每一层都是一个有序的链表,排列顺序为由高层到底层,都至少包含两个链表节点,分别是head节点和tail节点。
3、最底层的链表包含了所有的元素。
4、如果一个元素出现在某一层的链表中,那么该层之下的链表也全都会出现(上一层的元素是当前层的元素的子集)。
5、链表中的每个节点都包含两个指针,一个指向同一层的下一个链表节点,另一个指向下一层的同一个链表节点;
跳跃表的主要操作:
1、数据结构定义
2、初始化表
3、查找
4、插入
5、删除
下面是跳跃表的大体结构:

一、数据结构定义
(1)定义节点
#define MAX_LEVEL 10
typedef struct listNode {
int key;
int value;
struct listNode *next[1];
}listNode;
(2)定义跳跃表
typedef struct skipList {
int level;
listNode *head;
}skipList;
二、初始化表
listNode* createNode(int level, int key, int value)
{
listNode *pnode = (listNode*)malloc(sizeof(struct listNode));
if (pnode == NULL)
printf("out of space");
pnode->key = key;
pnode->value = value;
return pnode;
}
skipList* initskipList()
{
skipList *pSkL = (skipList*)malloc(sizeof(struct skipList));
if (pSkL == NULL)
printf("out of space");
pSkL->head = createNode(MAX_LEVEL-1,0,0);
for (int i = 0; i < MAX_LEVEL; i++) {
pSkL->head->next[i] = NULL;
}
return pSkL;
}
三、查找 find
从最高层的链表节点开始,如果要查找的节点比当前节点要大和比当前层的下一节点要小,那么往下查找。即与下一层链表节点的下一个节点进行比较,以此类推,一直找到最底层的最后一个节点,如果找到则返回,反之则返回空。
listNode* search(skipList* pSkL, int target)
{
listNode *p = pSkL->head;
listNode *q = NULL;
int k = pSkL->level;
for (int i = k - 1; i >= 0; i--) {
while ((q = p->next[i]) && (q->key <= target)) {
if (q->key == target)
return q;
}
p = q;
}
return NULL;
}
四、插入 insert
首先需要查找到在每层待插入位置,然后需要随机产生一个层数,最后就是从高层至下插入,插入时算法和普通链表的插入完全相同。
bool insert(skipList *pSkL, int key, int value)
{
listNode *new_node[MAX_LEVEL];
listNode *p, *q = NULL;
p = pSkL->head;
int k = pSkL->level;
for (int i = k - 1; i >= 0; i++) {
while ((q = p->next[i]) && (q->key < key)) {
p = q;
}
new_node[i] = p;
}
if (q&&q->key == key)
return false;
k = randomLevel();
if (k > pSkL->level) {
for (int i = pSkL->level; i < k; i++) {
new_node[i] = pSkL->head;
}
pSkL->level = k;
}
for (int i = 0; i < k; i++) {
q->next[i] = new_node[i]->next[i];
new_node[i]->next[i] = q;
}
return true;
}
五、删除 delete
从最高层的链表开始查找待删除节点,若待删除的节点比当前节点要大和比当前层的下一节点要小,那么往下一层查找。若找到则删除该层的该节点以及删除以下层的该节点。删除成功之后,重新调整链表层数,某一层数少于2个节点,则删除这一层链表。
bool Delete(skipList *pSkL, int key)
{
listNode *update[MAX_LEVEL];
listNode *p, *q = NULL;
p = pSkL->head;
int k = pSkL->level;
for (int i = k - 1; i >= 0; i--) {
while ((p = q->next[i]) && (q->key < key))
p = q;
update[i] = p;
}
if (q&&q->key == key) {
for (int i = 0; i < pSkL->level; i++) {
if (update[i]->next[i] == q)
update[i]->next[i] = q->next[i];
}
}
free(q);
for (int i = pSkL->level - 1; i >= 0; i--) {
if (pSkL->head->next[i] == NULL)
pSkL->level--;
}
return true;
}