跳跃表

跳跃表是对有序的链表增加上附加的前进链接,增加是以随机化的方式进行的,所以在列表中的查找可以快速的跳过部分列表。它的效率可以做到和平衡树相同的平均时间复杂度O(logN),其空间复杂度为O(N);
跳跃列表的算法有同平衡树一样的渐进的预期时间边界,并且更简单、更快速和使用更少的空间。

性质
1、有很多层结构(链表)组成
2、每一层都是一个有序的链表,排列顺序为由高层到底层,都至少包含两个链表节点,分别是head节点和tail节点。
3、最底层的链表包含了所有的元素。
4、如果一个元素出现在某一层的链表中,那么该层之下的链表也全都会出现(上一层的元素是当前层的元素的子集)。
5、链表中的每个节点都包含两个指针,一个指向同一层的下一个链表节点,另一个指向下一层的同一个链表节点;

跳跃表的主要操作:
1、数据结构定义
2、初始化表
3、查找
4、插入
5、删除
下面是跳跃表的大体结构:
跳跃表_第1张图片
一、数据结构定义
(1)定义节点
#define MAX_LEVEL  10 
typedef struct listNode {
	int key;
	int value;
	struct listNode *next[1];
}listNode;
(2)定义跳跃表
typedef struct skipList {
	int level;
	listNode *head;
}skipList;
二、初始化表
listNode* createNode(int level, int key, int value)
{
	listNode *pnode = (listNode*)malloc(sizeof(struct listNode));
	if (pnode == NULL)
		printf("out of space");
	pnode->key = key;
	pnode->value = value;
	return pnode;
}

skipList* initskipList()
{
	skipList *pSkL = (skipList*)malloc(sizeof(struct skipList));
	if (pSkL == NULL)
		printf("out of space");
	pSkL->head = createNode(MAX_LEVEL-1,0,0);
	for (int i = 0; i < MAX_LEVEL; i++) {
		pSkL->head->next[i] = NULL;
	}
	return pSkL;
}
三、查找 find
从最高层的链表节点开始,如果要查找的节点比当前节点要大和比当前层的下一节点要小,那么往下查找。即与下一层链表节点的下一个节点进行比较,以此类推,一直找到最底层的最后一个节点,如果找到则返回,反之则返回空。
listNode* search(skipList* pSkL, int target)
{
	listNode *p = pSkL->head;
	listNode *q = NULL;
	int k = pSkL->level;

	for (int i = k - 1; i >= 0; i--) {
		while ((q = p->next[i]) && (q->key <= target)) {
			if (q->key == target)
				return q;
		}
		p = q;
	}
	return NULL;
}
四、插入 insert
首先需要查找到在每层待插入位置,然后需要随机产生一个层数,最后就是从高层至下插入,插入时算法和普通链表的插入完全相同。 
bool insert(skipList *pSkL, int key, int value)
{
	listNode *new_node[MAX_LEVEL];
	listNode *p, *q = NULL;
	p = pSkL->head;
	int k = pSkL->level;

	for (int i = k - 1; i >= 0; i++) {
		while ((q = p->next[i]) && (q->key < key)) {
			p = q;
		}
		new_node[i] = p;
	}
	if (q&&q->key == key)
		return false;

	k = randomLevel();
	if (k > pSkL->level) {
		for (int i = pSkL->level; i < k; i++) {
			new_node[i] = pSkL->head;
		}
		pSkL->level = k;
	}

	for (int i = 0; i < k; i++) {
		q->next[i] = new_node[i]->next[i];
		new_node[i]->next[i] = q;
	}
	return true;
}
五、删除 delete
从最高层的链表开始查找待删除节点,若待删除的节点比当前节点要大和比当前层的下一节点要小,那么往下一层查找。若找到则删除该层的该节点以及删除以下层的该节点。删除成功之后,重新调整链表层数,某一层数少于2个节点,则删除这一层链表。
bool Delete(skipList *pSkL, int key)
{
	listNode *update[MAX_LEVEL];
	listNode *p, *q = NULL;
	p = pSkL->head;
	int k = pSkL->level;

	for (int i = k - 1; i >= 0; i--) {
		while ((p = q->next[i]) && (q->key < key))
			p = q;
		update[i] = p;
	}

	if (q&&q->key == key) {
		for (int i = 0; i < pSkL->level; i++) {
			if (update[i]->next[i] == q)
				update[i]->next[i] = q->next[i];
		}
	}

	free(q);
	for (int i = pSkL->level - 1; i >= 0; i--) {
		if (pSkL->head->next[i] == NULL)
			pSkL->level--;
	}
	return true;
}


你可能感兴趣的:(数据结构,经典数据结构)