skip list

跳錶是個機率性數據結構,能夠被看做是二叉樹的一個變種。跳錶是由William Pugh在1990年發明的。它是一種用戶維護有序元素的數據結構。
一個跳錶,應該具備如下特徵:
1.一個跳錶應該有幾個層(level)組成;
2.跳錶的第一層包含全部的元素;
3.每一層都是一個有序的鏈表;
4.若是元素x出如今第i層,則全部比i小的層都包含x;
5.第i層的元素經過一個down指針指向下一層擁有相同值的元素;
6.在每一層中,-1和1兩個元素都出現(分別表示INT_MIN和INT_MAX);
7.Top指針指向最高層的第一個元素。html

跳錶的構造過程是:
一、給定一個有序的鏈表。
二、選擇連表中最大和最小的元素,而後從其餘元素中按照必定算法隨即選出一些元素,將這些元素組成有序鏈表。這個新的鏈表稱爲一層,原鏈表稱爲其下一層。
三、爲剛選出的每一個元素添加一個指針域,這個指針指向下一層中值同本身相等的元素。Top指針指向該層首元素
四、重複二、3步,直到再也不能選擇出除最大最小元素之外的元素。node

複雜度:
1.The expected number of levels is O( log n )
(here n is the numer of elements)
2.The expected time for insert/delete/find is O( log n )
3.The expected size (number of cells) is O(n )算法

 

關於時空效率的證實:
1. 空間複雜度 O(n):
對於每層的期待:第一層n,第二層n/2,第三層n/22,...,直到 n/2log n=1。因此,總空間需求:
S = n + n/2 + n/22 + ... + n/2log n < n(1 + 1/2 + 1/22 + ... + 1/2∞) =2n
所以他的空間複雜度爲 2n = O(n)spring

2. Skip List高度:
對每層來講,它會向上增加的機率爲1/2,則第m層向上增加的機率爲1/2m;n個元素,則在m層元素數目的期待爲Em = n/2m;當Em = 1,m = log2n即爲層數的期待。故其高度期待爲 Eh = O(log n)。
*關於「高几率(high probability)」的定義:
(參考【3】【4】)
對於事件A,若是它發生的機率至少爲1-cα/nα,其中cα僅取決於α,那麼咱們稱它爲高几率。
在犧牲時間和/或空間的狀況下,咱們能夠選擇α的值。數據結構

3. 查找的複雜度:
claim:在高几率的前提下,查找的時間複雜度爲O(log n)
4. 插入的複雜度:
claim:在高几率的前提下,插入的時間複雜度爲O(log n)
首先經過查找找到要插入的位置:O(log n)
以後進行插入,同時對每層進行對應的更新(依照機率決定是否向上增加):o(log n)dom

5. 刪除的複雜度:
claim:在高几率的前提下,刪除的時間複雜度爲O(log n)ide

參考資料:
http://www.kernelchina.org/algorithm/SL.ppt
http://epaperpress.com/sortsearch/skl.html
http://www.spongeliu.com/63.html
http://www.cnblogs.com/flyfy1/archive/2011/02/24/1963347.html
http://courses.csail.mit.edu/6.046/spring04/handouts/skiplists.pdfspa

/**
 *
跳錶是個機率性數據結構,能夠被看做是二叉樹的一個變種。跳錶是由William Pugh在1990年發明的。它是一種用戶維護有序元素的數據結構。
一個跳錶,應該具備如下特徵:
1.一個跳錶應該有幾個層(level)組成;
2.跳錶的第一層包含全部的元素;
3.每一層都是一個有序的鏈表;
4.若是元素x出如今第i層,則全部比i小的層都包含x;
5.第i層的元素經過一個down指針指向下一層擁有相同值的元素;
6.在每一層中,-1和1兩個元素都出現(分別表示INT_MIN和INT_MAX);
7.Top指針指向最高層的第一個元素。

跳錶的構造過程是:
一、給定一個有序的鏈表。
二、選擇連表中最大和最小的元素,而後從其餘元素中按照必定算法隨即選出一些元素,將這些元素組成有序鏈表。這個新的鏈表稱爲一層,原鏈表稱爲其下一層。
三、爲剛選出的每一個元素添加一個指針域,這個指針指向下一層中值同本身相等的元素。Top指針指向該層首元素
四、重複二、3步,直到再也不能選擇出除最大最小元素之外的元素。

複雜度:
1.The expected number of levels is O( log n )
(here n  is the numer of elements)
2.The expected time for insert/delete/find is O( log n )
3.The expected size (number of cells) is O(n )

關於時空效率的證實:
1. 空間複雜度 O(n):
    對於每層的期待:第一層n,第二層n/2,第三層n/22,...,直到 n/2log n=1。因此,總空間需求:
    S = n + n/2 + n/22 + ... + n/2log n < n(1 + 1/2 + 1/22 + ... + 1/2∞) =2n
    所以他的空間複雜度爲 2n = O(n)

2. Skip List高度:
    對每層來講,它會向上增加的機率爲1/2,則第m層向上增加的機率爲1/2m;n個元素,則在m層元素數目的期待爲Em = n/2m;當Em = 1,m = log2n即爲層數的期待。故其高度期待爲 Eh = O(log n)。
*關於「高几率(high probability)」的定義:
    (參考【3】【4】)
    對於事件A,若是它發生的機率至少爲1-cα/nα,其中cα僅取決於α,那麼咱們稱它爲高几率。
     在犧牲時間和/或空間的狀況下,咱們能夠選擇α的值。

3. 查找的複雜度:
  claim:在高几率的前提下,查找的時間複雜度爲O(log n)
4. 插入的複雜度:
   claim:在高几率的前提下,插入的時間複雜度爲O(log n)
    首先經過查找找到要插入的位置:O(log n)
    以後進行插入,同時對每層進行對應的更新(依照機率決定是否向上增加):o(log n)

5. 刪除的複雜度:
   claim:在高几率的前提下,刪除的時間複雜度爲O(log n)


參考資料:
http://www.kernelchina.org/algorithm/SL.ppt
http://epaperpress.com/sortsearch/skl.html
http://www.spongeliu.com/63.html
http://www.cnblogs.com/flyfy1/archive/2011/02/24/1963347.html
http://courses.csail.mit.edu/6.046/spring04/handouts/skiplists.pdf
 */

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


#define MAX_LEVEL 10  //the max level

/**
 * node
 */
typedef struct nodeStructure {
    int key;
    int value;
    struct nodeStructure *forward[MAX_LEVEL];
    int name;
} nodeStructure;

/**
 * skip list
 */
typedef struct skiplist {
   int level;
   nodeStructure *header;
} skiplist;

/**
 * create node
 */
nodeStructure* createNode(int level,int key,int value) {
    nodeStructure *ns = (nodeStructure *) malloc(sizeof(nodeStructure));
    for(int i = 0; i < level;i++) {
        ns->forward[i] = NULL;
    }
    ns->key = key;
    ns->value = value;
    ns->name = key;
    return ns;
}

/**
 * initate skiplist
 */
skiplist* createSkiplist() {
    skiplist *sl = (skiplist *) malloc(sizeof(skiplist));
    sl->level = 0;
    sl->header = createNode(MAX_LEVEL - 1,0,0);
    for(int i = 0; i < MAX_LEVEL; i ++){
       sl->header->forward[i] = NULL;
    }

    return sl;
}

/**
 * just like throw coins
 */
int randomLevel() {
    int k = 1;
    while(rand()%2) {
        k++;
    }

    k = (k < MAX_LEVEL) ? k : MAX_LEVEL;
    return k;
}

bool insert(skiplist *sl, int key, int value) {
   nodeStructure *update[MAX_LEVEL];
   nodeStructure *p,*q;
   p = sl->header;
   int k = sl->level;
   //Search from top level to low
   for(int i = k - 1 ; i >= 0; i -- ) {
        while((q = p->forward[i]) && (q->key < key)) {
             p = q;
        }

        update[i] = p;    //若新的key所存在第i層,則當前節點的第i個forword會指向新節點
   }

   if(q && q->key == key) {
       return false;
   }
   //建立新的節點
   int new_level = randomLevel();
   if( new_level > sl->level) {
        for(int i = sl->level; i < new_level; i++){
            update[i] = sl->header;  //header的第level--k 層的下一節點都將指向新節點
        }

        sl->level = new_level;
   }

   q = createNode(new_level,key,value);
   for(int i = 0; i < new_level; i ++) {
        q->forward[i] = update[i]->forward[i];
        update[i]->forward[i] = q;
        //printf("%d\n",update[i]->forward[i]->value);
   }

   return true;
}


nodeStructure* search(skiplist *sl, int key) {
   nodeStructure *p,*q = NULL;
   p = sl->header;
   int level = sl->level;
   for( int i = level - 1; i >= 0; i--){
       while((q=p->forward[i]) && (q -> key < key)) {
           p = q;
       }

       if(q && q->key == key) {
           return q;
       }
   }
   return NULL;
}

bool deleteSL(skiplist *sl, int key){
    nodeStructure *p,*q = NULL;
    nodeStructure *update[MAX_LEVEL];
    int level = sl->level;
    p = sl->header;

    for(int i = level - 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];
                 //printf("update[%d]->name:%d\n",i,update[i]->name);
             } else { //我的以爲當不等時,i既是q的level數,不須要再往下遍歷
                 break;
             }
        }

        free(q);

        //若是被刪的是最高level的節點,需維護新跳錶
        for( int i = sl->level - 1; i >= 0; i --) {
            if(sl->header->forward[i] == NULL) {
                sl->level --;
            }
        }
        return true;
    }
   return false;
}

/**
 * 從最高層開始打印
 */
void printSL(skiplist *sl) {
   nodeStructure *p,*q = NULL;
   int level = sl->level;

   for(int i = level - 1; i >= 0; i--) {
         p = sl->header;
         while((q=p->forward[i])) {
             printf("%d(%d) -> ",q->key,q->value);
             p=q;
         }

         printf("\n");
   }

   printf("\n");
}

int main() {
    skiplist *sl = createSkiplist();
    for(int i = 1; i <= 19; i++) {
      insert(sl,i,i*2);
    }

    printSL(sl);

    //search
    nodeStructure* i = search(sl,4);
    printf("key=>%d,value=>%d\n",i->key,i->value);

    bool b = deleteSL(sl,4);
    if(b) {
        printf("Delete success\n");
    }

    printSL(sl);
    return 0;
}
View Code
相關文章
相關標籤/搜索