数据结构——跳表Skip List

news2024/10/7 5:53:10

本文对跳表的定义、实现、应用等进行简单总结。

一、 介绍

1.定义
跳表(Skip List):是一种概率性数据结构,由William Pugh在1990年提出,主要用于在有序的元素集合上进行快速的搜索、插入和删除操作。跳表的效率与平衡树相当,但实现起来更简单,它通过维护多层链表来提高查找效率。
2. 实现原理
在原有的有序链表上面增加了多级索引,通过索引进行二分查找从而实现高效率查找,其每种操作(搜索、插入、删除)的平均复杂性均为O(logn)
3.特点

特点描述
结构多层链表,每层是下层的子集。
查找效率平均和最坏情况的时间复杂度均为 (O(\log n)),通过多层结构实现快速跳转。
插入效率平均和最坏情况的时间复杂度也是 (O(\log n)),每个新元素通过随机机制决定其存在哪些层中。
删除效率平均和最坏情况的时间复杂度为 (O(\log n)),通过定位到元素并在其存在的每层中删除。
空间复杂度由于节点在多个层级中重复,空间复杂度较单一链表高。
实现简便相较于平衡树和散列表,跳表的实现更直接,调整结构更简单。
用途适用于需要大量动态插入和删除的有序数据集,如数据库和索引系统。

二、跳表的基本结构

  1. 跳表是一组排序的链表,它们分层堆叠在一起,每个层级都包含了部分或全部元素,但每个上层都是下层的一个稀疏子集。
  • 底层(Level 0):包含所有元素的完整链表
  • 上层:每一层都是下一层的稀疏子集,包含的元素逐层减少,每个元素向上晋级的概率通常是固定的(例如1/2)
  • 节点:不仅包含数据,还包含指针:指向同层下一个节点、上层或下层的指针。
  • 示例:
    在这里插入图片描述

2. 跳表的基本操作
(1)查找操作
查找从最顶层开始,如果当前层的下一个节点值大于查找值,就下降到下一层继续查找,直到最底层。如果找到目标值,则查找成功;否则,查找失败。
(2)插入操作
插入元素时,先在底层插入该元素,然后通过抛硬币的方式(随机决定)决定是否将该元素提升到上层。这个过程可能会一直持续到顶层。
(3)删除操作
删除元素先找到该元素(如上所述的查找方式),然后从最底层向上逐层删除该元素。

三、跳表的应用

1. 数据库索引

  • 快速查找:跳表提供了快速的查找性能,适合用作数据库中的索引结构,特别是在需要频繁插入和删除操作的数据库表中。
  • 范围查询:跳表可以有效地支持范围查询,这使得它非常适合在需要进行范围搜索的数据库索引中使用。

2. 缓存系统

  • 有序缓存:在缓存系统中,跳表可以用来保持缓存条目的有序性,便于实现如LRU(最近最少使用)等缓存淘汰算法。

3. 内存管理

  • 动态内存分配:跳表可以用于动态内存分配器中,以追踪空闲内存块的大小和位置,快速分配和释放内存。

4. 并发编程

  • 锁机制:跳表的结构使其更容易被分割成多个独立的部分,这样可以减少锁的竞争,适合并发环境。

5. 时间序列数据

  • 股票和金融数据:跳表适合存储和查询时间序列数据,如股票价格和交易量,支持高效的插入和查询操作。

6. 网络路由

  • 路由表:跳表可以用于网络路由表的实现,快速匹配IP地址和对应的路由。

7. 实时消息系统

  • 消息排序和检索:在需要实时处理和检索大量有序消息的系统中,跳表提供了一个高效的解决方案。

8. 多级索引

  • 文件系统索引:文件系统可以使用跳表来组织文件的元数据,特别是在需要频繁修改文件系统结构时。

四、Java实现跳表

1. 节点类定义

class SkipListNode<T> {
    T value;
    SkipListNode<T>[] forward; // 数组用来存储不同层的下一个节点

    public SkipListNode(int level, T value) {
        this.value = value;
        // 注意:数组索引从 0 开始,但是层级从 1 开始计数
        this.forward = new SkipListNode[level + 1];
    }
}

2. 跳表类定义

import java.util.Random;

class SkipList<T extends Comparable<? super T>> {
    private SkipListNode<T> head;
    private int maxLevel;
    private int level;
    private Random random;

    public SkipList() {
        // 最大层数设置为 16,实际应用中可以根据数据规模调整
        maxLevel = 16;
        level = 0;
        // 头节点的层级最大,所有层都有
        head = new SkipListNode<>(maxLevel, null);
        random = new Random();
    }

    // 生成随机层级
    private int randomLevel() {
        int lvl = 1;
        while (random.nextInt() % 2 == 0 && lvl < maxLevel) {
            lvl++;
        }
        return lvl;
    }

    // 查找方法
    public boolean search(T target) {
        SkipListNode<T> current = head;
        for (int i = level; i >= 0; i--) {
            while (current.forward[i] != null && current.forward[i].value.compareTo(target) < 0) {
                current = current.forward[i];
            }
        }
        current = current.forward[0];
        return current != null && current.value.compareTo(target) == 0;
    }

    // 插入方法
    public void insert(T value) {
        SkipListNode<T>[] update = new SkipListNode[maxLevel + 1];
        SkipListNode<T> current = head;
        for (int i = level; i >= 0; i--) {
            while (current.forward[i] != null && current.forward[i].value.compareTo(value) < 0) {
                current = current.forward[i];
            }
            update[i] = current;
        }
        current = current.forward[0];

        if (current == null || !current.value.equals(value)) {
            int lvl = randomLevel();
            if (lvl > level) {
                for (int i = level + 1; i <= lvl; i++) {
                    update[i] = head;
                }
                level = lvl;
            }
            SkipListNode<T> newNode = new SkipListNode<>(lvl, value);
            for (int i = 0; i <= lvl; i++) {
                newNode.forward[i] = update[i].forward[i];
                update[i].forward[i] = newNode;
            }
        }
    }

    // 删除方法
    public void delete(T value) {
        SkipListNode<T>[] update = new SkipListNode[maxLevel + 1];
        SkipListNode<T> current = head;
        for (int i = level; i >= 0; i--) {
            while (current.forward[i] != null && current.forward[i].value.compareTo(value) < 0) {
                current = current.forward[i];
            }
            update[i] = current;
        }
        current = current.forward[0];

        if (current != null && current.value.equals(value)) {
            for (int i = 0; i <= level; i++) {
                if (update[i].forward[i] != current) break;
                update[i].forward[i] = current.forward[i];
            }
            while (level > 0 && head.forward[level] == null) {
                level--;
            }
        }
    }
}

五、跳表与红黑树、B树、B+树

数据结构平均查找时间复杂度平均插入时间复杂度平均删除时间复杂度空间效率实现复杂度特点与应用场景
跳表(O(\log n))(O(\log n))(O(\log n))较低较低易于实现和理解,适用于需要快速插入和删除的场景,如缓存系统
红黑树(O(\log n))(O(\log n))(O(\log n))较高保持平衡的二叉搜索树,适用于需要保持数据平衡的场景,如操作系统的各类调度
B树(O(\log n))(O(\log n))(O(\log n))广泛用于数据库和文件系统索引,优化磁盘读写效率和减少I/O操作
B+树(O(\log n))(O(\log n))(O(\log n))优化用于数据库和文件系统索引,叶节点互联提高区间查询效率

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1864623.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AD手动添加网络

AD手动添加网络&#xff0c;&#xff08;用于不画原理图直接画PCB用&#xff09;一看就懂_ad不用原理图画pcb-CSDN博客https://blog.csdn.net/feifeiccode/article/details/107198441#:~:text%E6%B7%BB%E5%8A%A0%E8%A6%81%E6%B7%BB%E5%8A%A0%E7%9A%84%E7%BD%91%E7%BB%9C,%E6%8C…

12个RAG常见痛点及解决方案

Barnett等人的论文《Seven Failure Points When Engineering a Retrieval Augmented Generation System》介绍了RAG的七个痛点&#xff0c;我们将其延申扩展再补充开发RAG流程中常遇到的另外五个常见问题。并且将深入研究这些RAG痛点的解决方案&#xff0c;这样我们能够更好地在…

【Vue】集成富文本编辑器

这文章使用的是wangeditor插件&#xff0c;官网地址&#xff1a;wangEditor&#xff0c;这个比较简单 安装 npm i wangeditor --save 使用 <div id"editor"></div>import E from "wangeditor"const editor new E("#editor") e…

qt 打开pdf 三种方式

1.openurl是一种方式 11 12行 2.qprocess是一种 23 24 25行 3.这个fk项目的插件实现的 但是这个插件有点复杂 里面有很多继承 我没看懂具体每一层跳转逻辑 但是使用没有问题

VMware Workstation搭建Windows Server2019主备AD域控详细操作步骤

版本 虚拟机版本 VMware Workstation 16 Prp 16.2.5 build-20904516 服务器系统版本 具体操作 安装第一台虚拟机服务器 首先先创建一台Windows Server2019虚拟机&#xff0c;可以参考VMware Workstation安装Windows Server2019系统详细操作步骤-CSDN博客 克隆第一台虚拟机…

1.k8s:架构,组件,基础概念

目录 一、k8s了解 1.什么是k8s 2.为什么要k8s &#xff08;1&#xff09;部署方式演变 &#xff08;2&#xff09;k8s作用 &#xff08;3&#xff09;Mesos&#xff0c;Swarm&#xff0c;K8S三大平台对比 二、k8s架构、组件 1.k8s架构 2.k8s基础组件 3.k8s附加组件 …

基于springboot+vue的梦幻玩具乐园的设计与实现(在线购物平台)

需要源码和论文的小伙伴可以私信博主&#xff08;有偿&#xff09; ​​​​​课题目的与意义 随着互联网的不断普及与在线销售平台的迅猛发展&#xff0c;在线购物日益受到广大消费者的青睐与追捧。通过构建基于Spring BootVue的在线玩具商城&#xff0c;可以为玩具制造商、…

STM32之三:中断外部中断

目录 1. 什么是中断 1.1 中断概念 1.2 中断优先级 1.3 中断嵌套 2.STM32中断 2.1 NVIC中断优先级 3 外部中断 3.1 EXTI简介 3.2 EXTI中断/事件线 3.3 EXTI功能框图 3.4 中断和事件的区别&#xff1f; 3.5 什么时候用外部中断&#xff1f; 3.怎么使用STM32中断 3.…

1、Python编程入门:从硬件基础到解释器类型

Python是一种免费、开源、跨平台、动态、面向对象的编程语言。它以其简洁易读的语法和强大的功能而闻名&#xff0c;广泛应用于各种领域&#xff0c;如Web开发、数据分析、人工智能等。本文将介绍Python的基本概念、执行方式以及常用的Linux命令&#xff0c;帮助初学者快速入门…

用英文介绍伦敦:London The Empire MEGACITY

London: The Empire MEGACITY Link: https://www.youtube.com/watch?vZM7TBKD3a5U London is the capital of the United Kingdom and was the world’s largest city until 1925. Once the center of the massive British Empire, it is now a mature, well-planned metrop…

基于高度的纹理混合shader

基于高度的纹理混合shader 原文&#xff1a;基于高度的纹理混合shader - 知乎 (zhihu.com) 最近支持一个使用unity2021的项目&#xff0c;发现urp自带的Terrain/Lit shader已经自带高度混合了&#xff0c;看了下和我当初写的那个基本差不多&#xff0c;感觉稍微要比我的严谨一…

刷代码随想录有感(118):动态规划——打家劫舍II

题干&#xff1a; 代码&#xff1a; class Solution { public:int solve(vector<int>& nums, int start, int end){if(start end)return nums[start];if(nums.size() 0)return 0;if(nums.size() 1)return nums[0];vector<int>dp(nums.size(), 0);dp[start]…

vscode连接SSH

1、安装Remote-SSH插件 2、点击左下角&#xff0c;选择SSH 3、点击连接到主机后&#xff0c;添加新的SSH主机&#xff0c;示例ssh 用户ip 4、点击服务器&#xff0c;输入密码登录服务器 5、可在远程资源管理器选项卡中查看 6、可以在ssh设置中打开ssh配置文件 config中的文件…

Bad attr `class` with message: unexpected ```

小程序不支持模板字符串吗&#xff1f; | 微信开放社区 小程序不支持模版字符串。。。

一个项目学习Vue3---创建一个 Vue 应用

步骤1&#xff1a;安装符合要求的node版本 目前官网要求使用的node.js版本为18.3及其以上 所以我们要安装node.js 18.3及其以上版本 NVM安装教程&#xff1a;一个项目学习Vue3---NVM和NPM安装-CSDN博客 若不想安装NVM&#xff0c;可以直接下载适合自己的node版本Node.js — …

3D资产爆发,轻量化需求再度冲高,见证下一代3D崛起!

数字经济不断发展&#xff0c;3D资产和实体经济迎来深度融合的窗口期&#xff0c;3D资产应用外延催生大量新场景、新业态&#xff0c;一个3D资产构建的数字世界正出现在我们眼前。 数字经济不断发展&#xff0c;3D资产和实体经济迎来深度融合的窗口期&#xff0c;3D资产应用外…

django restframework 多对多模型 —— python

模型 图书和作者是多对多关系 class Book(models.Model):book_namemodels.CharField(max_length40)pricemodels.DecimalField(max_digits4,decimal_places2)publishmodels.ForeignKey(to"Publish",on_deletemodels.CASCADE,related_name"publish")authorm…

odoo 去掉在线聊天的删除和编辑内容

描述 odoo在线聊天功能中,在原有的聊天记录中是可以进行编辑和删除的 这使得产生很多不可控原因,乱改,乱删等 所以要进行屏蔽此功能 优化前 优化后 升级 mail 模块刷新即可。 <Dropdown t-if="messageActions.actions.length gt quickActionCount"onStateCha…

英伟达连跌3日,传字节与博通合作研发AI芯片,讯飞星火V4.0周四发布

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 更多资源欢迎关注 每日行业新闻 1、英伟达单日下跌6.7%&#xff0c;拖累标普500指数和纳指走低 昨夜&#xff0c;英伟达暴跌6.7%&#xff0c;创两个月以来最大单日跌幅&#xff0c;为连续三个交易日下跌&#xff0c;市…

Spring的jar包下载(最新版6.0版本)

1.在Spring官网的projects下面点击spring-framework 2.进入github官网 3.进入github后往下滑&#xff0c;点击Spring Framework Artifacts 4.往下滑找到 点击 5.在左边先点击Artifacts&#xff0c;在右边找到 libs-snapshot&#xff0c;展开libs-snapshot&#xff08;之前其他…