跳躍表

Skip List定義

Skip List 完整實(shí)現(xiàn)

//每個節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)
typedef  struct nodeStructure  
{  
    int key;    
    int value;  
    struct nodeStructure *forward[1];  
}nodeStructure;  

//跳躍表的數(shù)據(jù)結(jié)構(gòu)
typedef  struct skiplist  
{  
    int level;  
    nodeStructure *header;  
}skiplist;  

下面是跳表的基本操作

節(jié)點(diǎn)的創(chuàng)建
nodeStructure* createNode(int level,int key,int value)  
{  
 
  nodeStructure *ns=(nodeStructure *)malloc(sizeof(nodeStructure)+level*sizeof(nodeStructure*));    
 
   ns->key=key;    
   ns->value=value;    
   return ns;    
}  

列表的初始化
列表的初始化需要初始化頭部,并使頭部每層(根據(jù)事先定義的MAX_LEVEL)指向末尾(NULL)得运。

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;  
}  
插入元素

插入元素的時候元素所占有的層數(shù)完全是隨機(jī)的蛾默,通過隨機(jī)算法產(chǎn)生

int randomLevel()    
{  
    int k=1;  
    while (rand()%2)    
        k++;    
    k=(k<MAX_LEVEL)?k:MAX_LEVEL;  
    return k;    
}  

跳表的插入需要三個步驟坪蚁,第一步需要查找到在每層待插入位置,然后需要隨機(jī)產(chǎn)生一個層數(shù),最后就是從高層至下插入两残,插入時算法和普通鏈表的插入完全相同裤纹。

bool insert(skiplist *sl,int key,int value)  
{  
    nodeStructure *update[MAX_LEVEL];  
    nodeStructure *p, *q = NULL;  
    p=sl->header;  
    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;  
    }  
 
    //產(chǎn)生一個隨機(jī)層數(shù)K  
    //新建一個待插入節(jié)點(diǎn)q  
    //一層一層插入  
    k=randomLevel();  
    //更新跳表的level  
    if(k>(sl->level))  
    {  
        for(int i=sl->level; i < k; i++){  
            update[i] = sl->header;  
        }  
        sl->level=k;  
    }  
  
    q=createNode(k,key,value); 
    //逐層更新節(jié)點(diǎn)的指針委刘,和普通列表插入一樣  
    for(int i=0;i<k;i++)  
    {  
        q->forward[i]=update[i]->forward[i];  
        update[i]->forward[i]=q;  
    }  
    return true;  
}  

紅色區(qū)域?yàn)檩o助數(shù)組update的內(nèi)容

刪除節(jié)點(diǎn)

刪除節(jié)點(diǎn)操作和插入差不多,找到每層需要刪除的位置服傍,刪除時和操作普通鏈表完全一樣钱雷。不過需要注意的是,如果該節(jié)點(diǎn)的level是最大的吹零,則需要更新跳表的level罩抗。

bool deleteSL(skiplist *sl,int key)  
{  

   nodeStructure *update[MAX_LEVEL];   
   nodeStructure *p,*q=NULL;  
   p=sl->header;  
 
   //從最高層開始搜  
   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);  
       //如果刪除的是最大層的節(jié)點(diǎn)灿椅,那么需要重新維護(hù)跳表的  
       for(int i=sl->level-1; i >= 0; i--){    
           if(sl->header->forward[i]==NULL){    
               sl->level--;    
           }    
       }    
       return true;  
   }  
   else  
       return false;  
}  

查找

跳表的優(yōu)點(diǎn)就是查找比普通鏈表快套蒂,當(dāng)然查找操作已經(jīng)包含在在插入和刪除過程,實(shí)現(xiàn)起來比較簡單茫蛹。

int search(skiplist *sl,int key)  
{  
    nodeStructure *p,*q=NULL;  
    p=sl->header;  
    //從最高層開始搜  
    int k=sl->level;  
    for(int i=k-1; i >= 0; i--){  
        while((q=p->forward[i])&&(q->key<=key))  
        {  
            if(q->key==key)  
            {  
                return q->value;  
            }  
            p=q;  
        }  
    }  
    return NULL;  
}  


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末操刀,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子婴洼,更是在濱河造成了極大的恐慌骨坑,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柬采,死亡現(xiàn)場離奇詭異欢唾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)粉捻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門礁遣,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人肩刃,你說我怎么就攤上這事祟霍。” “怎么了盈包?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵沸呐,是天一觀的道長。 經(jīng)常有香客問我续语,道長垂谢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任疮茄,我火速辦了婚禮滥朱,結(jié)果婚禮上根暑,老公的妹妹穿的比我還像新娘。我一直安慰自己徙邻,他們只是感情好排嫌,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著缰犁,像睡著了一般淳地。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上帅容,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天颇象,我揣著相機(jī)與錄音,去河邊找鬼并徘。 笑死遣钳,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的麦乞。 我是一名探鬼主播蕴茴,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼姐直!你這毒婦竟也來了倦淀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤声畏,失蹤者是張志新(化名)和其女友劉穎撞叽,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體插龄,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡能扒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了辫狼。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡辛润,死狀恐怖膨处,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情砂竖,我是刑警寧澤真椿,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站乎澄,受9級特大地震影響突硝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜置济,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一解恰、第九天 我趴在偏房一處隱蔽的房頂上張望锋八。 院中可真熱鬧,春花似錦护盈、人聲如沸挟纱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽紊服。三九已至,卻和暖如春胸竞,著一層夾襖步出監(jiān)牢的瞬間欺嗤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工卫枝, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留煎饼,地道東北人。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓剃盾,卻偏偏與公主長得像腺占,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子痒谴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容

  • Redis為什么用跳表而不用平衡樹积蔚? 本文是《Redis內(nèi)部數(shù)據(jù)結(jié)構(gòu)詳解》系列的第六篇意鲸。在本文中,我們圍繞一個Re...
    meng_philip123閱讀 3,996評論 0 26
  • 前面已經(jīng)說了倒排索引的基本原理了,原理非常簡單漱贱,也很好理解槐雾,關(guān)鍵是如何設(shè)計第二個倒排表,倒排表的第二列也很好設(shè)計幅狮,...
    吳YH堅閱讀 998評論 0 1
  • 跳表(skip List)是一種隨機(jī)化的數(shù)據(jù)結(jié)構(gòu)募强,基于并聯(lián)的鏈表,實(shí)現(xiàn)簡單崇摄,插入擎值、刪除、查找的復(fù)雜度均為O(log...
    luoxn28閱讀 1,494評論 0 0
  • 最近在研究常用的索引結(jié)構(gòu)逐抑,包括基于內(nèi)存的和基于硬盤的結(jié)構(gòu)鸠儿。本文介紹skiplist的基本實(shí)現(xiàn)原理,從gfsfg85...
    從此啟航閱讀 1,737評論 0 0
  • 最近在看redis源碼厕氨,其中看到跳躍表的部分进每。無奈大學(xué)期間數(shù)據(jù)結(jié)構(gòu)學(xué)的基本上都快忘沒了汹粤,在網(wǎng)上找了個介紹跳躍表的兩...
    MentallyL閱讀 510評論 0 2