skiplist

数据量较大(百万级), 且要求部分有序(类似堆)或者全有序, 支持插入和删除。

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--;
	}
};


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
es fst skiplist 是 ElasticSearch 中的一种数据结构,用于实现有序的 key-value 存储和检索。skiplist 是一种基于链表和跳跃表的数据结构,可以在插入、删除和查找操作中实现较好的性能。 es fst skiplist 的核心思想是将数据按照 key 的有序性进行组织和存储,通过构建多层级的链表和跳跃表,以提高数据的查找效率。数据在 skiplist 中按照 key 的升序排列,每个节点都包含一个 key-value 对。节点之间通过指针进行连接,跳跃表通过添加额外的指针层次来提供一个快速跳转的路径。 使用 es fst skiplist 有以下几个优点: 1. 有序性:es fst skiplist 可以按照 key 的有序性进行存储和检索,这使得范围查询和有序遍历等操作更加高效。 2. 插入和删除性能:由于 skiplist 的特性,插入和删除操作具有良好的性能,平均时间复杂度为 O(log n),比一般基于平衡二叉树的数据结构性能更好。 3. 空间效率:相对于其他平衡二叉树结构,es fst skiplist 的占用空间较小,对于大规模数据存储来说更加节省空间。 4. 并发性:es fst skiplist 的设计支持并发访问和更新,可以提供较高的并发性能。 总而言之,es fst skiplist 是 ElasticSearch 中一种高效的数据结构,通过利用有序性和跳跃表的特性,提供高效的数据存储和检索功能。它在 ElasticSearch 中的应用可以加快查询速度,提高并发性能,适用于需要有序性和高效检索的场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值