跳跃表(skip list)的原理

跳表是一种优化链表访问的数据结构,通过增加多级索引,实现更快的查找效率。相比传统的链表,跳表可以达到O(log n)的查找时间复杂度,而插入和删除操作也保持了链表的灵活性。文章介绍了跳表的基本原理,包括如何通过随机概率确定新节点的层数,并提供了简单的实现概述。
摘要由CSDN通过智能技术生成

学过编程的都知道,数据结构中有一种数据结构叫做链表。

它的简单实现如下:

struct Node {
   
	T v;
	Node* nxt;
};

struct List {
   
	Node Head;
};

它的简单示意图如下:
在这里插入图片描述

链表有什么特点呢?

它一般是与数组比的,为什么呢,因为数组的优点就是链表的缺点,链表的优点就是数组的缺点。它们很有比较性。

链表是不连续的内存,所以新增元素不用改变原来已有元素的内存位置,很方便(跟数组比)。

但是,它访问很慢,因为单纯的链表这种结构访问元素的方式很笨重,就是一个一个访问。然而数组就很快了,由于它是连续的内存,所以能很快算出下一个元素的位置。如果我们需要某个确定索引位置的元素,数组比链表快。

想一下链表访问慢的原因。

是因为它的访问方式决定了它访问很慢,因为它一次访问唯一的一个元素(这个元素一般就是下一个元素)。因为它一个结点只能访问一个其他的结点。

那么,可不可以一次可以访问多个元素呢?

能不能一次访问两个呢,或者一次访问三个?

当然是可以的。

这就是跳表。

下图示意一下什么是跳表。

在这里插入图片描述

先看到,跳表的最底层其实就是链表(一个元素接着一个)。然后上面那么一层层的结点,是什么意思呢?

就是跳跃的意思,就是打破单个链表结点一次只能访问一个结点带来的慢速度。

拿a这个节点来说明一下。

(请注意把最底层的结点和它上面一层一层的结点看成一个整体。)

a这个节点可以访问到三个元素,是b,c,e。分别跳了1步,2步,4步。
b这个节点可以访问到一个元素,是c。跳了1步。
c这个节点可以访问到两个元素,是c,e。分别跳了1步,2步。

所以此时我们从头节点访问元素的步骤如下:

访问的节点 跳表的路径 跳表所需访问元素的个数 链表的路径 链表所需访问元素的个数
a a 1 a 1
b a->b 2 a->b 2
c a->c 2 a->b->c 3
d a->c->d 3 a->b->c->d 4
e a->e 2 a->b->c->d->e 5
f a->e->f 3 a->b->c->d->e->f 6
g a->e->g 3 a->b->c->d->e->f->g 7

如上图,相比较而言是不是快了。

跳表的时间复杂度是O(log n),比链表O(n)快多了。

感觉跟树状数组有点像。就是一个是数组,一个是链表。

那么跳表新增一个结点的时候,需要确定它的层数,如何确定新增节点的层数?

我们容易知道,一个跳表,有n/2的结点只有一层,有n/4的结点有两层,有n/8的结点有三层。

根据理论上的统计我们确定一个结点层数的概率就是,对于一个未知结点。它有1/2的可能是一层,1/4的可能是两层,1/8的可能是三层。。。

所以对于一个新增结点,我们随机给层数。

下面是它的简单实现:

/// @file skip_list.cpp
/// @brief wait for check
/// @author zhaolu
/// @version 1.0
/// @date 2020-03-07
/// @copyright Copyright (c) 2020 zhaolu. All Rights Reserved.

#include <string>
#include <random>
#include <iostream>

template<typename T>
class node {
   
	private:
		unsigned random_level() const {
   
			std::random_device rd; 
			std::mt19937 generator(rd());
		   	unsigned level = 1;

		   	for (int i = 1; i < 16; ++i) {
   
		    	if (generator() % 2 == 1) {
   
		    		++level;
		    	
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值