SkipList 跳跃链表 ⛵Data Structures and Algorithms⚓

前言

跳跃链表 是一种随机化的数据结构,目前开源软件 RedisLevelDB 都有用到它,它的效率和红黑树以及 AVL 树 不相上下,但跳表的原理相当简单,只要你能熟练操作链表,就能轻松实现一个 SkipList

有序链表

给出以下有序链表:
在这里插入图片描述
从该有序链表中搜索元素 < 23, 59, 72 > ,需要比较的次数分别为 < 2, 6, 8 >,总共比较的次数为 2 + 6 + 8 = 16 次。有没有优化的算法吗? 链表是有序的,但不能使用二分查找。类似二叉搜索树,我们把一些节点提取出来,作为索引。得到如下结构:
在这里插入图片描述
此时,继续从该有序链表中搜索元素 < 23, 59, 72 > ,需要比较的次数分别为 < 3, 5, 4 >,总共比较的次数为 3 + 5 + 4 = 12 次。

提取出来作为一级索引,这样搜索的时候就可以减少比较次数了。

从一级索引提取一些元素出来,作为二级索引,三级索引…
在这里插入图片描述
元素不多,体现不出优势,如果元素足够多,这种索引结构就能体现出优势来了。

跳跃链表

跳跃链表的结构:
在这里插入图片描述
跳跃链表具有如下性质:

  • 由很多层结构组成
  • 每一层都是一个有序的链表
  • 最底层 (level 1) 的链表包含所有元素
  • 如果一个元素出现在 level item 的链表中,则它在 level item 之下的链表也都会出现。
  • 每个节点包含两个指针,一个指向同一链表中的下一个元素,一个指向下面一层的元素。

跳跃链表的查找

在这里插入图片描述
假设查找 26

  1. 比较 31, 比 31 小,->down
  2. 比较 7, 比 7 大,->next
  3. 比较 31, 比 31 小,->down
  4. 比较 19, 比 19 大,->next
  5. 比较 31, 比 31 小,->down
  6. 比较 23, 比 23 大,->next
  7. 比较 26, 等于 26, 找到了节点。

跳跃链表的插入及初始化

在这里插入图片描述
head 开始判断是否插入,每层插入概率为 1/2,即用查找的思想,从上往下,若成功,在该 ==level == 插入新节点,若不成功,继续往下, level 1 必须插入。

判断是否插入通过随机数返回 boolrand() % 2 判断。

跳跃链表的初始化就是通过批量节点进行插入操作。

具体概率例如:

  • level 1 = 1
  • level 2 = 1 / 2
  • level 3 = (1 / 2)^ 2
  • level 4 = (1 / 2)^ 3
  • level n = (1 / 2)^(n - 1)

跳跃链表的删除

在这里插入图片描述
用查找的思想,从上往下,查找到需要删除的节点进行删除操作。

跳跃链表的时间复杂度

SkipList 由多层级单向有序链表组成。搜索,插入,删除的平均复杂度是 O(*log n*)

SkipList 代码示范

SkipList.h

/*
*** SkipList
*/

#ifndef _SKIPLIST
#define _SKIPLIST

#include <iostream>
#include <stdlib.h>
#include <stdio.h>

const int _MAXLEVEL = 4;

template<class T>
class Node_Skip
{
   
public:
	T info;

	Node_Skip* next;
	Node_Skip* down;

	Node_Skip();
};

template<class T>
Node_Skip<T>::Node_Skip()
{
   
	next = NULL;
	down = NULL;
}

template<class T>
class SkipList
{
   
private:
	Node_Skip<T>* head;

public:
	SkipList();
	~SkipList();

	bool Empty() const;	// 判断空表
	unsigned int Length(unsigned int length = 0) const; // 返回表长(地表)
	bool HalfSwitch(unsigned int) const; // “1/2” 概率
	bool Inse
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值