跳跃表原理+代码完整

转载了参考文章的部分内容,代码自己敲了一遍,记录下来用来自己复习用。

参考文章地址:http://dsqiu.iteye.com/blog/1705530

本文内容框架:

§1 Skip List 介绍

§2 Skip List 定义以及构造步骤

  §3 Skip List 完整实现

§1 Skip List 介绍

Skip List是一种随机化的数据结构,基于并联的链表,其效率可比拟于二叉查找树(对于大多数操作需要O(log n)平均时间)。基本上,跳跃列表是对有序的链表增加上附加的前进链接,增加是以随机化的方式进行的,所以在列表中的查找可以快速的跳过部分列表(因此得名)。所有操作都以对数随机化的时间进行。Skip List可以很好解决有序链表查找特定值的困难。 

§2 Skip List 定义以及构造步骤 

Skip List定义

像下面这样(初中物理经常这样用,这里我也盗用下):

一个跳表,应该具有以下特征:

  1. 一个跳表应该有几个层(level)组成;
  2. 跳表的第一层包含所有的元素;
  3. 每一层都是一个有序的链表;
  4. 如果元素x出现在第i层,则所有比i小的层都包含x;
  5. 第i层的元素通过一个down指针指向下一层拥有相同值的元素;
  6. 在每一层中,-1和1两个元素都出现(分别表示INT_MIN和INT_MAX);
  7. Top指针指向最高层的第一个元素。

构建有序链表

link list

的一个跳跃表如下:


Skip List构造步骤:

       1、给定一个有序的链表。

2、选择连表中最大和最小的元素,然后从其他元素中按照一定算法(随机)随即选出一些元素,将这些元素组成有序链表。这个新的链表称为一层,原链表称为其下一层。
3、为刚选出的每个元素添加一个指针域,这个指针指向下一层中值同自己相等的元素。Top指针指向该层首元素
4、重复2、3步,直到不再能选择出除最大最小元素以外的元素。

§3 Skip List 完整实现

下面来定义跳表的数据结构(基于C)下面代码都是验证过的:

/*************************************************************************
	> File Name: skip_list.c
	> Author: 
	> Mail: 
	> Created Time: Sat 24 Mar 2018 07:41:24 PM PDT
 ************************************************************************/

#include
#include

#define LEVEL_MAX_LEN 10
typedef char bool;
#define true 1
#define false 2

//跳跃表节点结构体
typedef struct SkipListNode{
    int key;
    int data;
    struct SkipListNode *forward[1];
}SkipListNode;

//跳跃表链表结构
typedef struct SkipList{
    int level;
    struct SkipListNode *head;
}SkipList;

//节点初始化
SkipListNode *CreatSkipNode(int level, int key, int data)
{
    SkipListNode *newNode = (SkipListNode *)malloc(sizeof(SkipListNode) + level*sizeof(SkipListNode));
    if(newNode == NULL)
        return NULL;
    newNode->key = key;
    newNode->data = data;

    return newNode;
}

//初始化跳表
SkipList *CreatSkipList()
{
    SkipList *newlist = (SkipList *)malloc(sizeof(SkipList));
    if(newlist == NULL)
        return NULL;
    newlist->head = CreatSkipNode(LEVEL_MAX_LEN-1, 0, 0);
    for(int i = LEVEL_MAX_LEN-1; i >= 0; i--){
        newlist->head->forward[i] = NULL;
    }
    return newlist;
}

//随机产生层数
int RandLevel()
{
    int k = 1;
    while(rand()%2)
        k++;
    return (k < LEVEL_MAX_LEN)?k:LEVEL_MAX_LEN;
}

//插入节点
bool InsertNode(SkipList *sl, int key, int data)
{
    SkipListNode *update[LEVEL_MAX_LEN];
    SkipListNode *p, *q = NULL;
    p = sl->head;
    int k = sl->level;
    //从高到低找节点插入的位置,update存储每一层应该插入的位置
    for(int i = k-1; i >= 0; i--){
        while((q = p->forward[i]) && (q->key < key)){
            p = q;
        }
        update[i] = p;
    }
    //不能插入相同的key
    if(q && q->key == key){
        return false;
    }

    //产生一个随机层数
    //新建一个待插入节点q,层层插入
    k = RandLevel();
    //更新跳跃表的level
    if(k > (sl->level)){
        for(int i = (sl->level); i < k; ++i){
            update[i] = sl->head;
        }
        sl->level = k;
    }

    q = CreatSkipNode(k, key, data);
    //逐层更新节点的指针,跟普通链表的插入一样
    for(int i = 0; i < k; ++i){
        q->forward[i] = update[i]->forward[i];
        update[i]->forward[i] = q;
    }
    return true;
}

//搜索指定的key
int SearchByKey(SkipList *sl, int key)
{
    SkipListNode *p, *q = NULL;
    int k = sl->level;
    p = sl->head;
    for(int i = k-1; i >= 0; i--){
        while((q = p->forward[i]) && (q->key <= key)){
            if(q->key == key)
                return (q->key);
            p = q;
        }
    }
    return 0;
}

//删除指定的key
bool deleteNode(SkipList *sl, int key)
{
    SkipListNode *p, *q = NULL;
    SkipListNode *update[LEVEL_MAX_LEN];
    p = sl->head;
    int k = sl->level;
    for(int i = k-1; i >= 0; i--){
        while((q = p->forward[i]) && (q->key < key)){
            p = q;
        }
        update[i] = p;
    }
    if(q && q->key == key){
        //逐层删除,和删除普通链表一样
        for(int i = 0; i < sl->level; ++i){
            if(update[i]->forward[i] == q){
                update[i]->forward[i] = q->forward[i];
            }
        } 
        free(q);
        //如果删除的是最大层的节点,那末需要重新维护跳表
        for(int i = sl->level-1; i >= 0; i--){
            if(sl->head->forward[i] == NULL){
                sl->level--;
            }
        }
        return true;
    }else{
        return false;
    }
}

//打印跳跃表
void PrintSkipList(SkipList *sl)
{
    SkipListNode *p, *q = NULL;
    //从最高层开始打印
    int  k = sl->level;
    for(int i = k-1; i >= 0; i--){
        p = sl->head;
        while(q = p->forward[i]){
            printf("%d->", p->data);
            p = q;
        }
        printf("\n");
    }
    printf("\n");
}

int main(void)
{
    SkipList *sl = CreatSkipList();
    for(int i = 0; i <= 19; ++i){
        InsertNode(sl, i, i*2);
    }
    PrintSkipList(sl);
    int m = SearchByKey(sl, 4);
    printf("serch value = %d\n", m);
    
    bool b = deleteNode(sl, 4);
    if(b){
       printf("删除成功\n");
    }
    PrintSkipList(sl);
    system("pause");
    return 0;
}


你可能感兴趣的:(跳跃表原理+代码完整)