数据量较大(百万级), 且要求部分有序(类似堆)或者全有序, 支持插入和删除。
list 查找慢, 导致插入和删除慢
vector查找快, 但是插入和删除消耗大,会移动近半元素
set/map,与 skiplist性能同级别。 但是实现复杂。
skiplist 在redis中作为set的底层容器。 插入、查找、删除级别都是log(n)
//author: lovelychen_1005@163.com
/*改动:
0 改为c++类。
1 支持模板。 只是用简单类型测试过。 复杂类型未测试, 需要提供std::less<Key>
2 支持遍历。 方式是Peek取得头部; 如果需要删掉,Delete掉Peek的返回值即可
*/
#pragma once
#include <stdlib.h>
#include <stdio.h>
//http://www.cnblogs.com/liuhao/archive/2012/07/26/2610218.html
//http://in.sdo.com/?p=711
#define SKIPLIST_MAXLEVEL 25
template <typename Key> class SkipListNode;
template <typename Key> class SkipListLevel;
template <typename Key> class SkipListLevel {
public:
SkipListNode<Key> *forward;
};
template <typename Key> class SkipListNode {
SkipListNode();
~SkipListNode();
public:
Key score;
SkipListNode *backward;
SkipListLevel<Key> level[];
void Free()
{
::free(this);
}
static SkipListNode *CreateNode(int level, const Key & score) {
SkipListNode * sn = (SkipListNode *)(malloc(sizeof(*sn) + level*sizeof(SkipListLevel<Key>)));
sn->score = score;
return sn;
}
};
template <typename Key> class SkipList {
SkipList();
~SkipList();
public:
SkipListNode<Key> *header, *tail;
unsigned long length;
int level;
static SkipList *CreateList(void) {
int j;
SkipList *sl;
sl = (SkipList *)(malloc(sizeof(*sl)));
sl->level = 1;
sl->length = 0;
sl->header = SkipListNode<Key>::CreateNode(SKIPLIST_MAXLEVEL, 0);
for(j = 0; j < SKIPLIST_MAXLEVEL; j++) {
sl->header->level[j].forward = NULL;
}
sl->header->backward = NULL;
sl->tail = NULL;
return sl;
}
void Free() {
SkipListNode<Key> *node = this->header->level[0].forward, *next;
free(this->header);
while(node) {
next = node->level[0].forward;
node->Free();
node = next;
}
free(this);
}
const Key &Peek()
{
const static Key nullKey(0);
if(length <= 0) return nullKey;
SkipListNode<Key> *node = NULL;
for (int i = this->level - 1; i >= 0; i--) {
if (this->header->level[i].forward) {
node = this->header->level[i].forward; break;
}
}
return header->level[0].forward->score;
}
static int RandomLevel(void) {
int level = 1;
while((rand()&0xFFFF) < (0.5 * 0xFFFF))
level += 1;
return (level < SKIPLIST_MAXLEVEL) ? level : SKIPLIST_MAXLEVEL;
}
SkipListNode<Key> *Insert(const Key & score) {
SkipListNode<Key> *update[SKIPLIST_MAXLEVEL];
SkipListNode<Key> *node;
node = this->header;
int i, level;
for ( i = this->level-1; i >= 0; i--) {
while(node->level[i].forward && node->level[i].forward->score < score) {
node = node->level[i].forward;
}
update[i] = node;
}
level = RandomLevel();
if (level > this->level) {
for (i = this->level; i< level ;i++) {
update[i] = this->header;
}
this->level = level;
}
node = SkipListNode<Key>::CreateNode(level, score);
for (i = 0; i < level; i++) {
node->level[i].forward = update[i]->level[i].forward;
update[i]->level[i].forward = node;
}
node->backward = (update[0] == this->header? NULL : update[0]);
if (node->level[0].forward)
node->level[0].forward->backward = node;
else
this->tail = node;
this->length++;
return node;
}
int Delete(const Key &score) {
SkipListNode<Key> *update[SKIPLIST_MAXLEVEL], *node;
int i;
node = this->header;
for(i = this->level-1; i >= 0; i--) {
while (node->level[i].forward && node->level[i].forward->score < score) {
node = node->level[i].forward;
}
update[i] = node;
}
node = node->level[0].forward;
if (node && score == node->score) {
DeleteNode(node, update);
node->Free();
return 1;
} else {
return 0;
}
return 0;
}
int Search(const Key & score) {
SkipListNode<Key> *node;
int i;
node = this->header;
for (i = this->level-1; i >= 0 ;i--) {
while(node->level[i].forward && node->level[i].forward->score < score) {
node = node->level[i].forward;
}
}
node = node->level[0].forward;
if (node && score == node->score) {
printf("Found %d\n",(int)node->score);
return 1;
} else {
printf("Not found %d\n", (int)score);
return 0;
}
}
void Print() {
SkipListNode<Key> *node;
int i;
for (i = 0; i < SKIPLIST_MAXLEVEL; i++) {
printf("LEVEL[%d]: ", i);
node = this->header->level[i].forward;
while(node) {
printf("%d -> ", (int)(node->score));
node = node->level[i].forward;
}
printf("NULL\n");
}
}
private:
void DeleteNode(SkipListNode<Key> *x, SkipListNode<Key> **update){
int i;
for (i = 0; i < this->level; i++) {
if (update[i]->level[i].forward == x) {
update[i]->level[i].forward = x->level[i].forward;
}
}
if (x->level[0].forward) {
x->level[0].forward->backward = x->backward;
} else {
this->tail = x->backward;
}
while (this->level > 1 && this->header->level[this->level-1].forward == NULL)
this->level--;
this->length--;
}
};