跳表(SkipList)

来源:互联网 发布:阿里云建立二级域名 编辑:程序博客网 时间:2024/06/05 09:47

最近在看leveldb的源码,看到核心的skiplist时发现自己浑浑噩噩的,本来就不太懂,.h文件里还竟是模板迭代器啥的,于是决定还是先吧思路理清楚,都提倡不要重复发明轮子,但只有熟悉轮子的制作过程,用起来才可能得心应手啊。

这篇图文并茂的博文将跳表的基本操作描述的很不错:http://kenby.iteye.com/blog/1187303

为了便于忘了再看时能很快懂(源码真心不好看呀),下面的代码中很多地方都注释了一些我的理解

#include <cstdio>#include <cstdlib>#include <cstring>#define MAX_LEVEL10#define ALL_PART4struct SkipListNode{//dataint key;//level count the node appearsint height;//soft memberSkipListNode* next[1];};int RandomLevel(){int h = 1;while(rand() % ALL_PART == 0) ++h;return h;}SkipListNode* NewNode(int level){return reinterpret_cast<SkipListNode*>(malloc(sizeof(SkipListNode) + (level-1)*sizeof(SkipListNode*)));}void FreeNode(SkipListNode* p){free(p);p = NULL;}class SkipList{public:SkipList();~SkipList();bool Contain(int k)const;bool Insert(int k);bool Delete(int k);void Show()const;private:void findLastLessThan(int k, SkipListNode* arr[MAX_LEVEL])const;private:SkipListNode* head;};/*********************************** implementation *********************************/SkipList::SkipList(){head = NewNode(MAX_LEVEL);memset(head, 0, sizeof(SkipListNode) + (MAX_LEVEL-1)*sizeof(SkipListNode*));head->height = 1;}SkipList::~SkipList(){int i = 0, m = head->height;for(; i < m; ++i){//delete nodes with height iSkipListNode *p = head, *q = head->next[i];for(; q; q = p->next[i]){if(q->height == i+1){p->next[i] = q->next[i];FreeNode(q);}else p = q;}}FreeNode(head);}void SkipList::Show()const{puts("SkipList:");int m = head->height;for(; m; --m){printf("level %d: ", m-1);SkipListNode* p = head->next[m-1];bool first = true;for(; p; p = p->next[m-1]){if(first) first = false;else printf("-->");printf("%d", p->key);}puts("");}}void SkipList::findLastLessThan(int k, SkipListNode* arr[MAX_LEVEL])const{// puts("enter SkipList::findLastLessThan");SkipListNode *p = head, *q;int m = p->height;//find each level's last node whose key is smaller than kfor(int i = m-1; i >= 0; --i){//move horizontally for level iwhile((q = p->next[i]) && q->key < k) p = q;//p is last node in level i that has key smaller than karr[i] = p;// printf("head = %p, arr[%d] = %p\n", head, i, p);}// puts("leave SkipList::findLastLessThan");}bool SkipList::Contain(int k)const{SkipListNode* update[MAX_LEVEL], *q;findLastLessThan(k, update);q = update[0]->next[0];return q && q->key == k;}bool SkipList::Insert(int k){SkipListNode* update[MAX_LEVEL], *q;findLastLessThan(k, update);q = update[0]->next[0];// printf("head = %p, q = %p\n", head, q);//q is the first node in level 0, whose key is no lesser than kif(q && q->key == k) return false;//k is not in skiplist yet, find its highest appearing levelint h = RandomLevel(), m = head->height;// printf("height for %d is  %d\n", k, h);if(h > m){//we need to redirect update[m, h) to headfor(int i = m; i < h; ++i) update[i] = head;//need to change skiplist's whole heighthead->height = h;}//now insert k behind every update[0, h)SkipListNode* t = NewNode(h);t->key = k;t->height = h;for(int i = 0; i < h; ++i){t->next[i] = update[i]->next[i];update[i]->next[i] = t;}return true;}bool SkipList::Delete(int k){SkipListNode* update[MAX_LEVEL], *q;findLastLessThan(k, update);q = update[0]->next[0];//check k is in skip list or not, that is whether it appears in the lowest levelif(!q || q->key != k) return false;//update[] are k's previous nodes, redirect them to k's next onesfor(int i = q->height-1; i >= 0; --i){update[i]->next[i] = q->next[i];}FreeNode(q);//check if we need to change skiplist's whole heightint h = head->height;for(; h; --h){if(head->next[h-1]) break;}head->height = h;return true;}void test(){int cnt = 10, i;SkipList sl;puts("==== Insert ====");for(i = 0; i < cnt; ++i){if(sl.Insert(i)) printf("Insert %d into SkipList done\n", i);else printf("%d already in SkipList\n", i);if(sl.Insert(i)) printf("Insert %d into SkipList done\n", i);else printf("%d already in SkipList\n", i);}getchar();puts("==== Show ====");sl.Show();getchar();puts("==== Contain ====");for(i = 0; i < cnt; ++i){int v = rand() % (cnt + cnt / 2);if(sl.Contain(v)) printf("%d is in SkipList\n", v);else printf("%d is not in SkipList\n", v);}getchar();puts("==== Delete ====");for(i = cnt-1; i >= cnt/2; --i){if(sl.Delete(i)) printf("Delete %d from SkipList done\n", i);else printf("%d not in SkipList\n", i);if(sl.Delete(i)) printf("Delete %d from SkipList done\n", i);else printf("%d not in SkipList\n", i);}getchar();puts("==== Show ====");sl.Show();getchar();}int main(){test();puts("done");getchar();return 0;}


0 0
原创粉丝点击