跳表的由来及Java实现详解

跳表的由来及Java实现详解

1. 什么是跳表?

跳表(Skip List)是一种基于随机化的数据结构,用来实现有序数据的动态插入、删除和查找操作。跳表其实就是一个多层的单向链表,每一层的节点都是前一层节点的子节点,且每个节点都有概率生成更高层的后续节点。由于跳表适用于数据元素有序且动态插入、删除的情况,因此在一些高性能并发库的实现中有广泛的应用。

2. 跳表的发明历史

跳表的发明者为William Pugh,其于1990年在ACM上发表了名为Skipped List的文章,实现了一种以O(logN)时间复杂度平均的方法在跳表中进行查找、插入和删除操作,并将跳表的理论性质发扬光大地应用于同步算法的设计中。从此跳表开始受到广泛的研究和应用。

3. 跳表的Java实现

具体的Java代码实现可以参考如下的示例:

3.1 定义跳表节点类

class SkipListNode<T> {
    public T value;
    public SkipListNode<T>[] next;

    public SkipListNode(T value, int level) {
        this.value = value;
        this.next = new SkipListNode[level];
    }
}

SkipListNode类表示跳表的节点,包含了节点的值和跳表的前后指针,用于构建跳表的多层结构。

3.2 跳表类的定义

public class SkipList<T> {
    private static final double DEFAULT_PROBABILITY = 0.5; // 节点加入新的一层的概率

    private SkipListNode<T> head;
    private int levelCount;
    private int size;
    private Random random;
    private double probability;

    public SkipList() {
        this.head = new SkipListNode<T>(null, 0);
        this.levelCount = 1;
        this.size = 0;
        this.random = new Random();
        this.probability = DEFAULT_PROBABILITY;
    }

    // 查找节点
    public SkipListNode<T> find(T value) {
        SkipListNode<T> p = head;
        for (int i = levelCount - 1; i >= 0; i--) { // 从前往后找到每层的前序节点
            while (p.next[i] != null && p.next[i].value.compareTo(value) < 0) {
                p = p.next[i];
            }
        }
        if (p.next[0] != null && p.next[0].value.equals(value)) { // 如果最后一层的节点是目标节点则返回
            return p.next[0];
        }
        return null;
    }

    // 插入节点
    public void insert(T value) {
        int level = randomLevel(); // 随机生成插入节点的层数
        SkipListNode<T> newNode = new SkipListNode<T>(value, level);
        SkipListNode<T>[] update = new SkipListNode[level];
        SkipListNode<T> p = head;

        for (int i = level - 1; i >= 0; i--) { // 从前往后遍历每层,找到待插入节点的前序节点,并记录在update数组中
            while (p.next[i] != null && p.next[i].value.compareTo(value) < 0) {
                p = p.next[i];
            }
            update[i] = p;
        }

        for (int i = 0; i < level; i++) { // 从下往上构建新节点的指针链接
            newNode.next[i] = update[i].next[i];
            update[i].next[i] = newNode;
        }
        size++;
    }

    // 删除节点
    public void delete(T value) {
        SkipListNode<T>[] update = new SkipListNode[levelCount];
        SkipListNode<T> p = head;
        for (int i = levelCount - 1; i >= 0; i--) { // 从上到下遍历每层,找到待删除节点的前序节点,并记录在update数组中
            while (p.next[i] != null && p.next[i].value.compareTo(value) < 0) {
                p = p.next[i];
            }
            update[i] = p;
        }
        if (p.next[0] != null && p.next[0].value.equals(value)) { // 如果找到了目标节点,则开始删除操作
            for (int i = 0; i < levelCount; i++) { // 从上到下逐层删除
                if (update[i].next[i] != null && update[i].next[i].value.equals(value)) {
                    update[i].next[i] = update[i].next[i].next[i];
                }
            }
            size--;
        }
    }

    // 随机生成新节点的层数
    private int randomLevel() {
        int level = 1;
        while (random.nextDouble() < probability && level < 32) {
            level++;
        }
        return level;
    }
}

SkipList类表示跳表,包含了跳表的各种操作方法。find方法用于查找特定的值;insert方法用于插入新节点;delete方法用于删除节点。其中,randomLevel方法用于随机生成新节点的层数。

3.3 示例一:查找元素

public static void example1() {
    SkipList<Integer> list = new SkipList<>();
    for (int i = 0; i < 10; i++) { // 插入元素
        list.insert(i);
    }
    SkipListNode<Integer> node = list.find(5); // 查找元素
    System.out.println(node.value);
}

此示例中,首先构建了一个包含10个元素的跳表。然后通过调用find方法查找元素5所在的节点,并打印出节点的值。

3.4 示例二:删除元素

public static void example2() {
    SkipList<Integer> list = new SkipList<>();
    for (int i = 0; i < 10; i++) { // 插入元素
        list.insert(i);
    }
    list.delete(5); // 删除元素
    SkipListNode<Integer> node = list.find(5); // 查找元素
    System.out.println(node);
}

此示例中,首先构建了一个包含10个元素的跳表。然后通过调用delete方法删除元素5。最后通过调用find方法查找元素5所在的节点,并打印出结果null。

4. 总结

跳表是一种基于随机化的有序数据结构,适用于动态插入、删除和查找场景,具有O(logN)时间复杂度平均的特性。Java中可以通过定义SkipListNode和SkipList类来实现跳表的基本操作,为多种场景提供了高效的数据结构支持。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:跳表的由来及Java实现详解 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • android上superuser获取root权限原理解析

    Android上Superuser获取Root权限原理解析 什么是Superuser? 在Android系统中,有些应用程序需要获取Root权限才能够执行一些敏感操作,比如修改系统设置、进入系统目录等等。Superuser就是一种允许应用程序获取Root权限的工具。 当安装Superuser后,用户可以决定哪些应用程序可以访问Root权限,哪些应用程序被禁止…

    其他 2023年3月28日
    00
  • VS2015编译Qt5.7.0生成支持XP的静态库(很不错)

    VS2015编译Qt5.7.0生成支持XP的静态库(很不错) 在使用Qt进行开发时,有时需要生成静态库以供其他开发者使用,同时为了兼容Windows XP系统,可以使用以下步骤在VS2015中编译Qt5.7.0生成支持XP的静态库。 步骤一:下载Qt5.7.0源码包并解压 在官网下载Qt5.7.0源码,解压到本地的一个路径下,例如 C:\Qt\qt-ever…

    其他 2023年3月28日
    00
  • Nagios远程监控安装与配置详解图文第1/3页

    首先是Nagios的安装和配置步骤: Nagios远程监控安装与配置详解 安装Nagios服务器端 安装依赖项 Nagios 依赖以下软件包:gcc,glibc,glibc-common,gd,gd-devel,make,net-snmp。在 CentOS/RHEL 7 系统上执行以下命令: sudo yum install -y gcc glibc gli…

    other 2023年6月25日
    00
  • iPhone存储空间不足怎么办 快速让iPhone释放几个GB空间妙招

    iPhone存储空间不足怎么办:快速释放几个GB空间攻略 如果你的iPhone存储空间不足,以下是一些快速释放几个GB空间的妙招。这些方法可以帮助你清理不必要的文件和数据,以腾出更多的存储空间。 1. 删除不需要的应用程序和游戏 应用程序和游戏通常占据大量的存储空间。删除不再使用或不需要的应用程序和游戏是释放存储空间的最简单方法之一。 示例说明:假设你有一个…

    other 2023年8月1日
    00
  • Android实现滑块拼图验证码功能

    Android实现滑块拼图验证码功能攻略 简介 滑块拼图验证码是一种常见的人机验证方式,用于判断用户是否为真实用户而不是机器人。在Android应用中实现滑块拼图验证码功能可以提高应用的安全性。本攻略将详细介绍如何在Android应用中实现滑块拼图验证码功能。 步骤 步骤一:准备资源 首先,需要准备一张包含滑块和背景的图片作为验证码的背景图。 然后,需要准备…

    other 2023年8月20日
    00
  • C语言基于循环链表解决约瑟夫环问题的方法示例

    C语言基于循环链表解决约瑟夫环问题的方法示例 什么是约瑟夫环问题 约瑟夫环问题是一个著名的问题。问题描述如下: 有n个人(假设编号分别为1,2,3…n),这n个人围坐在一起形成一个圆圈,从1开始报数,每报数到m时,该人就离开圆圈出列,直到剩下最后一个人。求解最后一个人的编号。 解题思路 针对约瑟夫环问题,可以采用循环链表的数据结构进行解决。具体思路如下: 根…

    other 2023年6月27日
    00
  • 转:SqlServer2012自增列值突然增大1000的原因及解决方法

    转:SqlServer2012自增列值突然增大1000的原因及解决方法 最近有些开发者反馈他们使用SqlServer2012时,数据库表的自增列突然增大了1000个,这对于表中数据量较大的情况下显得异常夸张,特此总结原因及解决方法。 问题原因 主要原因就是Sql Server 2012在自增列管理上的性能优化,当自增列的当前值被完全使用时,SqlServer…

    其他 2023年3月28日
    00
  • 显卡oc和不带oc性能差距大吗 显卡oc和不带oc的区别对比

    显卡OC和不带OC性能差距大吗? 显卡OC(超频)是指通过调整显卡的工作频率来提高其性能。一般来说,显卡OC可以带来一定的性能提升,但具体的差距取决于多个因素,包括显卡本身的设计和制造质量,以及超频的程度和稳定性。 显卡OC的优势 性能提升:通过超频,显卡的工作频率可以提高,从而增加图形处理能力和帧率。这意味着在游戏或其他图形密集型任务中,显卡OC可以提供更…

    other 2023年8月6日
    00
合作推广
合作推广
分享本页
返回顶部