第一次看到這種數(shù)據(jù)結(jié)構(gòu)還是剛接觸ocean base架構(gòu)的時(shí)候。粗略掃了幾眼,以為是一個(gè)簡(jiǎn)單的二級(jí)索引,沒有仔細(xì)考慮就略過(guò)了。后來(lái)去北京出差,經(jīng)神夜路點(diǎn)播,遂明白這種鏈表式結(jié)構(gòu)的簡(jiǎn)約而不簡(jiǎn)單,有一種四兩撥千斤的優(yōu)雅。
Skip lists are a data structure that can be used in place of balanced trees. Skip lists use probabilistic balancing rather than strictly enforced balancing and as a result the algorithms for insertion and deletion in skip lists are much simpler and significantly faster than equivalent algorithms for balanced trees.
--William Pugh
相比于紅黑樹,B樹,AVL樹,跳表的實(shí)現(xiàn)相當(dāng)簡(jiǎn)單,同時(shí),由于其多維鏈表的特性,使得跳表可以支持無(wú)鎖的多讀一寫。(鏈表的多讀一寫無(wú)鎖實(shí)現(xiàn)方式這里就不展開了)。
不同于B樹,跳表的平衡性依靠隨機(jī)算法,在正常情況下,該結(jié)構(gòu)的查找,插入,刪除的時(shí)間復(fù)雜度都是logN。
先從一維鏈表開始,我們知道在鏈表中查找一個(gè)元素I的話,需要將整個(gè)鏈表遍歷一次。
如果是說(shuō)鏈表是排序的,并且節(jié)點(diǎn)中還存儲(chǔ)了指向前面第二個(gè)節(jié)點(diǎn)的指針的話,那么在查找一個(gè)節(jié)點(diǎn)時(shí),僅僅需要遍歷N/2個(gè)節(jié)點(diǎn)即可。
這基本上就是跳表的核心思想,其實(shí)也是一種通過(guò)“空間來(lái)?yè)Q取時(shí)間”的一個(gè)算法。
下面我們來(lái)看一個(gè)4層跳表示例:
查找時(shí)首先從高層開始查找,之后逐漸降低層次靠近數(shù)據(jù),完成定位。
插入操作:
由于跳表數(shù)據(jù)結(jié)構(gòu)整體上是有序的,所以在插入時(shí),需要首先查找到合適的位置,然后就是修改指針(和鏈表中操作類似),然后更新跳表的level變量。
補(bǔ)充一個(gè)數(shù)據(jù)節(jié)點(diǎn)層次確定算法:
int height = 1;
while (height < kMaxHeight && ((rnd_.Next() % kBranching) == 0))
{
height++;
}
可以發(fā)現(xiàn)層級(jí)越高的節(jié)點(diǎn)越少,因此跳表整體的指針開銷并不高。 相比于同級(jí)別的樹形實(shí)現(xiàn),跳表具有更快的速度,更低的空間開銷和更簡(jiǎn)單的實(shí)現(xiàn)。
/*
·* skipList.h
·*
·* ·Created on: 2013年8月7日
·* · · ·Author: sigh.xy
·*/
#ifndef SKIPLIST_H_
#define SKIPLIST_H_
#include <iostream>
#include <stack>
//rand
#include<stdlib.h>
template <class Key = int, class Value = int>
class Node
{
public:
Key key;
Value value;
Node(Key k, Value v) : key(k), value(v){}
Node(){}
};
template <class Key = int, class Value = int>
class Element
{
Node<Key, Value> node;
Element** next;
public:
Element() : next(NULL) {}
Element(Node<Key, Value> node, int level)
{
this->node = node;
next = new Element*[level];
for (int i = 0; i < level; i++)
{
next[i] = NULL;
}
}
void setNext(int place, Element* nElement)
{
next[place] = nElement;
}
Element* & getNext(int place)
{
return next[place];
}
Key getKey()
{
return node.key;
}
Value getValue()
{
return node.value;
}
~Element()
{
if (next)
{
delete[] next;
}
}
};
//declare
template <class Key, class Value>
class SkipIterator;
template <class Key = int, class Value = int, int MAXLEVEL = 4>
class SkipList
{
//head
Element<Key, Value>** head;
int randLevel(int level = MAXLEVEL);
void findWay(Key key, std::stack<Element<Key, Value>** >& pStack);
public:
typedef SkipIterator<Key, Value> Iterator;
SkipList()
{
head = new Element<Key, Value>*[MAXLEVEL];
for (int i = 0; i < MAXLEVEL; i++)
{
head[i] = NULL;
}
}
Value find(Key key);
bool insert(Key key, Value value);
Iterator begin()
{
return head[0];
}
Iterator end()
{
return Iterator();
}
//another kind of insert
//bool delKey(Key key);
~SkipList()
{
Element<Key, Value>* cur = head[0];
while (cur)
{
Element<Key, Value>* tmp = cur;
cur = cur->getNext(0);
delete tmp;
}
}
};
//查找數(shù)據(jù)
template <class Key, class Value, int MAXLEVEL>
Value SkipList<Key, Value, MAXLEVEL>::find(const Key key)
{
if (NULL == head)
{
return (Value) 0;
}
//std::cout << "ok" << std::endl;
int rawL = MAXLEVEL - 1;
Element<Key, Value>* cur = NULL;
//find the first < place
while (rawL >= 0)
{
if (head[rawL] && head[rawL]->getKey() == key)
{
return head[rawL]->getValue();
}
else if (head[rawL] && head[rawL]->getKey() < key)
{
cur = head[rawL];
break;
}
rawL--;
}
//std::cout << "rawL = " << rawL << std::endl;
while (rawL >= 0)
{
if (cur && cur->getKey() == key)
{
return cur->getValue();
}
else if (cur->getNext(rawL) && cur->getNext(rawL)->getKey() <= key)
{
cur = cur->getNext(rawL);
}
else
{
rawL--;
}
}
return (Value) 0;
}
//通過(guò)棧記錄查找路徑,用于插入操作。
template <class Key, class Value, int MAXLEVEL>
void SkipList<Key, Value, MAXLEVEL>::findWay(Key key,
std::stack<Element<Key, Value>** >& pStack)
{
int rawL = MAXLEVEL - 1;
Element<Key, Value>* cur = NULL;
//find the first < place
while (rawL >= 0)
{
if (head[rawL] && head[rawL]->getKey() < key)
{
cur = head[rawL];
break;
}
pStack.push(&head[rawL]);
rawL--;
}
while (rawL >= 0)
{
if (cur->getNext(rawL) && cur->getNext(rawL)->getKey() <= key)
{
cur = cur->getNext(rawL);
}
else
{
pStack.push(&cur->getNext(rawL));
rawL--;
}
}
}
//插入操作
template <class Key, class Value, int MAXLEVEL>
bool SkipList<Key, Value, MAXLEVEL>::insert(Key key, Value value)
{
int level = randLevel();
Element<Key, Value>* element =
new Element<Key, Value>(Node<Key, Value>(key, value), level);
std::stack<Element<Key, Value>**> pStack;
findWay(key, pStack);
for (int i = 0; i < level; i++)
{
element->getNext(i) = *pStack.top();
*(pStack.top()) = element;
//std::cout << "head = " << head[0]->getValue() << std::endl;
pStack.pop();
}
//std::cout << head[0]->getNext(0) << std::endl;
return true;
}
template <class Key, class Value, int MAXLEVEL>
int SkipList<Key, Value, MAXLEVEL>::randLevel(int level)
{
int height = 1;
while (height < MAXLEVEL && ((rand() % level) == 0))
{
height++;
}
return height;
}
//iterator
template <class Key, class Value>
class SkipIterator
{
private:
Element<Key, Value>* element;
public:
typedef Element<Key, Value> EType;
SkipIterator(Element<Key, Value>* e) : element(e) {}
SkipIterator()
{
element = NULL;
}
EType& operator*()
{
return *element;
}
void operator++()
{
element = element->getNext(0);
}
void operator++(int)
{
++*this;
}
bool operator!= (SkipIterator<Key, Value> right)
{
return this->element != right.element;
}
};
#endif /* SKIPLIST_H_ */
基于模版的某種實(shí)現(xiàn)方式?jīng)]有做很嚴(yán)格的測(cè)試,因此不保證正確性。
(原文時(shí)間2013-8-5)