IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Java版skiplist跳表详解 -> 正文阅读

[数据结构与算法]Java版skiplist跳表详解

skiplist简介

skiplist 是 一个概率型数据结构,查找、删除、插入的时间复杂度都是O(logN)。

skiplist是由多层有序的链表组成的,来加快查找速度。

其中第0层包含了所有元素,然后往上增加了多层的有序链表作为索引来加快查找速度。
在这里插入图片描述

skiplist组成

链表节点Node

public class Node {
        //存储的数据
        private int data = -1;
        /**
         * 表示当前节点位置的下一个节点所有层的数据,从上层切换到下层,就是数组下标-1,
         * forwards[3]表示当前节点在第三层的下一个节点。
         */
        private Node forwards[];
        
        //构造函数,构造一个占据n层的节点
        public Node(int level) {
            forwards = new Node[level];
        }
}

SkipList主要属性

public class SkipList {
    //跳表的允许的最大层数
    private static final int MAX_LEVEL = 16;
    //当前的最大层数
    private int levelCount = 0;
    //跳表的头节点,头节点的层数是最大层
    private Node head = new Node(MAX_LEVEL);
    private Random r = new Random();
}



randomLevel()

skiplist的精髓就在于随机算法,通过随机事件来决定是否为一个节点增加层数,可以灵活的控制索引的数量。如果想要占用少的内存,就可以指定一个小的概率来减少节点的层数。
当然如果节点层数变小,对应的查询效率有可能变慢。

private int randomLevel() {
    int level = 1;
    for (int i = 1; i < MAX_LEVEL; ++i) {
        //如果随机生成的数小于p,就增加层数。
        //如果想要增加目录,就将p赋予一个较大的数。
        if (r.next() < p) {
            level++;
        }
    }
    return level;
}

insert()

public void insert(int value) {
    //获取随机层数
    int level = randomLevel();
    //更新levelCount
    if (level > levelCount) {
        levelCount = level;
    }
    
    Node newNode = new Node(level);
    newNode.data = value;
    Node update[] = new Node[level];
    for (int i = 0; i < level; ++i) {
        update[i] = head;
    }

    Node p = head;
    // 从上层往下层逐层查找,update对应着每层的插入的前一个节点
    for (int i = level - 1; i >= 0; --i) {
        while (p.forwards[i] != null && p.forwards[i].data < value) {
            // 找到前一节点
            p = p.forwards[i];
        }
        //第i层 对应的插入位置 p 
        update[i] = p;

    }
    
    //依次向每层中插入数据
    for (int i = 0; i < level; ++i) {
        newNode.forwards[i] = update[i].forwards[i];
        update[i].forwards[i] = newNode;
    }

}

find()

查找函数,从上层往下层依次查找

public Node find(int value) {
    Node p = head;
    // 从最大层开始查找,找到前一节点,通过--i,移动到下层再开始查找
    for (int i = levelCount - 1; i >= 0; --i) {
        while (p.forwards[i] != null && p.forwards[i].data <= value) {
            // 找到前一节点
            p = p.forwards[i];
        }
    }

    if (p.forwards[0] != null && p.forwards[0].data == value) {
        return p.forwards[0];
    } else {
        return null;
    }
}

delete()

public void delete(int value) {
    Node[] update = new Node[levelCount];
    Node p = head;
    //找到每层的前置节点存储到update中
    for (int i = levelCount - 1; i >= 0; --i) {
        while (p.forwards[i] != null && p.forwards[i].data < value) {
            p = p.forwards[i];
        }
        update[i] = p;
    }
    
    //如果存在对应的元素
    if (p.forwards[0] != null && p.forwards[0].data == value) {
        //为每层更新对应的指针
        for (int i = levelCount - 1; i >= 0; --i) {
            //如果第i层的前置节点的下一个节点是要删除的值,就更新指针
            if (update[i].forwards[i] != null && update[i].forwards[i].data == value) {
                update[i].forwards[i] = update[i].forwards[i].forwards[i];
            }
        }
    }
}

总结

通过对应的函数,可以看出,跳表就是一个链表,只不过链表中的节点十分特殊,节点中有一个层数的概念,每一层都对应着有一个指针,指向另一个节点,代表着节点在对应层的下一个节点就是指针代表的节点。

链表查询的缺点就是当查询链表后半部分的数据的时候,需要先遍历前面的节点,这就白白浪费了事件。

跳表的核心思想就是通过随机算法将下层的链表选取部分代表抽取到上层。

这样的话,前半部分的很多元素在高层中会被省略。当查询高层链表的时候,即使是查询后半部分的数据,也可以快速的定位到节点所属的区间。加快了查询效率。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-10-04 13:05:02  更:2021-10-04 13:07:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 14:38:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码