博客
关于我
数据结构 - 跳跃链表
阅读量:238 次
发布时间:2019-02-28

本文共 4604 字,大约阅读时间需要 15 分钟。

数据结构 - 跳跃链表

为什么会有跳表?

在处理普通单链表时,我们需要从头节点依次遍历到目标节点,这种方法在节点数量较多时效率较低,时间复杂度为 O(N)。为了加快查找速度,我们可以尝试使用跳表的思想。

跳表的基本原理类似于二分查找法,通过建立多个索引层,每个索引层包含链表中的一部分节点。例如,假设我们有一个普通单链表,当我们想要查找55号节点时,可以通过跳表的多个索引层快速定位到目标节点,减少遍历的节点数量,实现 O(logN) 的查询时间复杂度。

跳表的结构

跳表的最底层通常是双向链表或单链表,而索引层一般是单链表。节点类的定义如下:

class ListNode:    def __init__(self, data=None):        self._data = data        self._forwards = []

跳表的实现类定义如下:

class SkipList:    _MAX_LEVEL = 16    def __init__(self):        self._level_count = 1        self._head = ListNode()        self._head._forwards = [None] * self._MAX_LEVEL

跳表元素查询

要查询13号节点,可以从最高层开始查找。如果当前层没有找到目标节点,就向下一层继续查找,直到找到目标节点或确定不存在该节点。

如果要查找11号节点,我们可以从最高层开始,发现13号节点比我们要找的11号节点大,于是退回7号节点,再从下一层查找,直到找到目标节点或确定不存在该节点。

查询实现代码如下:

def find(self, value):    p = self._head    for i in range(self._level_count - 1, -1, -1):        while p._forwards[i] and p._forwards[i]._data < value:            p = p._forwards[i]    return p._forwards[0] if p._forwards[0] and p._forwards[0]._data == value else None

跳表元素插入

在跳表中插入节点时,需要先找到插入位置,然后根据随机生成的层数调整节点间的指向关系。

插入实现代码如下:

def insert(self, value):    level = self._random_level()    if self._level_count < level:        self._level_count = level    new_node = ListNode(value)    new_node._forwards = [None] * level    update = [self._head] * level    p = self._head    for i in range(level - 1, -1, -1):        while p._forwards[i] and p._forwards[i]._data < value:            p = p._forwards[i]        update[i] = p    for i in range(level):        new_node._forwards[i] = update[i]._forwards[i]        update[i]._forwards[i] = new_node

随机层数生成函数如下:

def _random_level(self, p=0.5):    level = 1    while random.random() < p and level < self._MAX_LEVEL:        level += 1    return level

跳表元素删除

删除节点时,需要找到目标节点的前驱节点,并通过指针操作删除节点,确保索引层的正确性。

删除实现代码如下:

def delete(self, value):    update = [None] * self._level_count    p = self._head    for i in range(self._level_count - 1, -1, -1):        while p._forwards[i] and p._forwards[i]._data < value:            p = p._forwards[i]        update[i] = p    if p._forwards[0] and p._forwards[0]._data == value:        for i in range(self._level_count - 1, -1, -1):            if update[i]._forwards[i] and update[i]._forwards[i]._data == value:                update[i]._forwards[i] = update[i]._forwards[i]._forwards[i]

完整代码

from typing import Optionalimport randomclass ListNode:    def __init__(self, data=None):        self._data = data        self._forwards = []class SkipList:    _MAX_LEVEL = 16    def __init__(self):        self._level_count = 1        self._head = ListNode()        self._head._forwards = [None] * self._MAX_LEVEL    def find(self, value):        p = self._head        for i in range(self._level_count - 1, -1, -1):            while p._forwards[i] and p._forwards[i]._data < value:                p = p._forwards[i]        return p._forwards[0] if p._forwards[0] and p._forwards[0]._data == value else None    def insert(self, value):        level = self._random_level()        if self._level_count < level:            self._level_count = level        new_node = ListNode(value)        new_node._forwards = [None] * level        update = [self._head] * level        p = self._head        for i in range(level - 1, -1, -1):            while p._forwards[i] and p._forwards[i]._data < value:                p = p._forwards[i]            update[i] = p        for i in range(level):            new_node._forwards[i] = update[i]._forwards[i]            update[i]._forwards[i] = new_node    def delete(self, value):        update = [None] * self._level_count        p = self._head        for i in range(self._level_count - 1, -1, -1):            while p._forwards[i] and p._forwards[i]._data < value:                p = p._forwards[i]            update[i] = p        if p._forwards[0] and p._forwards[0]._data == value:            for i in range(self._level_count - 1, -1, -1):                if update[i]._forwards[i] and update[i]._forwards[i]._data == value:                    update[i]._forwards[i] = update[i]._forwards[i]._forwards[i]    def _random_level(self, p=0.5):        level = 1        while random.random() < p and level < self._MAX_LEVEL:            level += 1        return level    def __repr__(self):        values = []        p = self._head        while p._forwards[0]:            values.append(str(p._forwards[0]._data))            p = p._forwards[0]        return "-".join(values) if values else ""

示例使用代码:

if __name__ == "__main__":    l = SkipList()    for i in range(10):        l.insert(i)    print(l)    p = l.find(7)    print(p._data)    l.delete(3)    print(l)

如需了解更多关于跳跃链表的详细内容,可以参考相关技术文档或资料。

转载地址:http://fxvp.baihongyu.com/

你可能感兴趣的文章
Python-Asyncio TypeError:无法在‘;等待‘;表达式中使用对象DICT
查看>>
Python-AttributeError:‘;dict&39;对象没有属性‘;序列‘;
查看>>
Python-ldap:是否可以在不显式写入密码的情况下进行绑定?
查看>>
python出现 unknown encoding: idna 的处理方法
查看>>
Python出现 RuntimeError: dictionary changed size during iteration 的解决方法
查看>>
Python-numpy(2)数组的操作
查看>>
Python-Numpy的tile函数用法
查看>>
python-open函数
查看>>
Python-Pandas-将特定函数应用于给定级别-多索引数据框架
查看>>
python-queue队列通信
查看>>
python-ros No module named PyKDL
查看>>
python-social-auth 是否需要会话
查看>>
Python再获年度编程语言,微软或成最大赢家
查看>>
python-week5
查看>>
Python写表情包搜索工具(非常详细)零基础入门到精通,收藏这一篇就够了
查看>>
Python-【1】配置
查看>>
Python-从子文件夹执行绝对导入
查看>>
Python-刷新页面,直到元素可单击
查看>>
PYTHON-唤醒+VOSK+DEEPSEEK+离线合成-实现纯离线大模型问答
查看>>
Python-在Dash回调中重用函数
查看>>