leveldb之SkipList的簡單實現

2021-07-02 03:52:36 字數 2691 閱讀 7132

skiplist是鍊錶的變形,它在鍊錶的基礎上給每個元素增加了乙個高度,且每個元素的高度是乙個隨機值,因此skiplist是一種隨機化的資料結構。skiplist增、刪查、改的效率都非常高,是一種典型的以空間換時間的儲存方式。

常規的鍊錶如下:

而相同元素對應的skiplist結構如下:

由上可知,當要在鍊錶中查詢某個元素時,必須從煉表頭乙個乙個遍歷,而在skiplist中查詢某個元素時,查詢卻是跳躍的,因此將其稱為skiplist。

如要查詢元素25時,對於單鏈表,要遍歷到第9個節點才能找到。而對於skiplist,只需要經過2次比較即可(表頭到元素6再到25),效率非常高。

當查詢的效率高了之後,插入、刪除、修改的效率自然也就變高了

skiplist中的每個節點,都包含有乙個值和乙個陣列,其中陣列元素的個數即為當前節點的高度,陣列中對應位置的元素儲存的是指向同一高度的下一節點的指標(如next[0]指向level 0的下一節點,next[3]指向level 3的下一節點),因此陣列可用乙個二級指標表示。

template

struct skiplistnode;

skiplist類中的成員變數只包含了當前鍊錶的最大高度和表頭

template

class skiplist

~skiplist();

bool insert(const

std::pair& value);

node* find(keytype& key) const;

bool remove(keytype& key);

int getlevel() const

private:

node* createnode(std::pairkey,int level);

void destroynode(node *node);

int level_;//skiplist中節點的最大高度

node *head_;//表頭元素

};

skiplist在建構函式中呼叫createnode()得到表頭節點,表頭首先會初始化系統規定的最大高度個陣列元素,假設最大高度為4

node* createnode(std::pairvalue,int level)
經過建構函式構造的表頭如下:

鍊錶的增、刪、查、改中,查詢操作是最核心的,其他操作均是建立在查詢的基礎上的

1)查詢元素

node* find(keytype  key) const

node=node->next[0];

if(node==null||node->keyvalue.first!=key) return

null;

else

return node;

}

2)插入元素

bool insert(const std::pair& value)

node=node->next[0];

if(node!=null&&node->keyvalue.first==value.first) return

false;//若已存在於要插入元素的key值相等的,則不插入直接返回

int newlevel=getrandomlevel();//隨機產生要插入元素的高度

if(level_//當新的高度大於原來鍊錶中的最大高度時,說明此時從level_到newlevel高度均為空,還沒有初始值

for(int i=level_;i//則說明新節點從level_到newlevel的直接前驅都只會是head_,將其存放在update中

level_=newlevel;//更新此時鍊錶的最大高度

}node=createnode(value,newlevel);//建立新節點

for(int i=0;i//然後將新節點插入到skiplist中,基本操作與鍊錶相似,只不過節點的不同高度的直接前驅都不同

node->next[i]=update[i]->next[i];

update[i]->next[i]=node;

}return

true;

}

以要插入元素17為例(假設其他元素都已經存在),此時的level_=4

for(int i=level_-1;i>=0;--i)
得到後面要更新的節點update: update[3]=6,update[2]=6,update[1]=9,update[0]=12

同時newlevel=2

for(int i=0;i//與一般節點的插入類似,要對每一高度的節點更新插入

node->next[i]=update[i]->next[i];

update[i]->next[i]=node;

}

這樣就將元素插入到skiplist中

LevelDB之整體結構

資料庫和儲存引擎。資料庫往往是乙個比較豐富完整的系統,提供了sql查詢語言,事務和水平擴充套件等支援。然而儲存引擎則是小而精,純粹專注於單機的讀 寫 儲存。一般來說,資料庫底層往往會使用某種儲存引擎。目前開源的kv儲存引擎中,rocksdb是流行的乙個,mongodb和mysql底層可以切換成roc...

深入leveldb 初步認識leveldb

1.leveldb簡介 leveldb是google兩位工程師實現的單機版k v儲存系統,具有以下幾個特點 1.key和value都是任意的位元組陣列,支援記憶體和持久化儲存 2.資料都是按照key排序 3.使用者可以重寫排序函式 4.包含基本的資料操作介面,put key,value get ke...

LevelDB原始碼剖析之Memtable 1

memtable是leveldb很重要的一塊,leveldb的核心之一。我們肯定關注kv資料在memtable中是如何組織的,秘密在skip list中。在leveldb中,所有記憶體中的kv資料都儲存在memtable中,物理disk則儲存在sstable中。在系統執行過程中,如果memtable...