前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >算法:跳跃表的实现

算法:跳跃表的实现

作者头像
超级大猪
发布2019-11-22 14:50:28
3390
发布2019-11-22 14:50:28
举报
文章被收录于专栏:大猪的笔记大猪的笔记

用python实现跳跃表

代码语言:javascript
复制
import random


class SkipList(object):
    def __init__(self):
        self.level = [None, None, None, None, None]

    def insert(self, node):
        pre_node = self._find_pre(node)
        node.prev = pre_node

        will_affect = []
        temp_node = pre_node
        while 1:
            if len(temp_node.level) < len(node.level):
                will_affect.append(temp_node)
                temp_node = temp_node.prev
            else:
                will_affect.append(temp_node)
                break

        for affect_node in will_affect:
            for k, p_node in enumerate(affect_node.level):
                if p_node is None or p_node.score > node.score:
                    if k < len(node.level):
                        # 修改指针
                        node.level[k] = p_node
                        affect_node.level[k] = node

    def _find_pre(self, node):
        pre_node = self
        while 1:
            for i in range(len(pre_node.level)-1, -1, -1):
                p_node = pre_node.level[i]
                if p_node is None:
                    continue
                elif p_node.score > node.score:
                    continue
                elif p_node.score <= node.score:
                    pre_node = p_node
                    break
            else:
                return pre_node


    def get_range(self, start_score, stop_score):
        start_node = self._find_pre(SkipListNode('', start_score))
        while 1:
            if isinstance(start_node, SkipList):
                start_node = start_node.level[0]
                break
            if isinstance(start_node.prev, SkipList):
                break
            if start_node.prev.score >= start_score:
                start_node = start_node.prev
            else:
                break

        result = []
        while 1:
            if start_node and start_score <= start_node.score <= stop_score:
                result.append(start_node)
                start_node = start_node.level[0]
            else:
                break
        return result


class SkipListNode(object):
    def __init__(self, key, score):
        self.key = key
        self.score = score
        self.prev = None
        self.level = []
        for i in range(0, random.randint(1,5)):
            self.level.append(None)

if __name__ == '__main__':
    # test

    skip_list = SkipList()

    node = SkipListNode('helloworld1', 1)
    skip_list.insert(node)

    node = SkipListNode('helloworld31', 3)
    skip_list.insert(node)

    node = SkipListNode('helloworld2', 2)
    skip_list.insert(node)

    node = SkipListNode('helloworld32', 3)
    skip_list.insert(node)

    node = SkipListNode('helloworld33', 3)
    skip_list.insert(node)

    result = skip_list.get_range(3, 3)
    assert len(result) == 3
    for node in result:
        print(node.key)
        print(node.score)
        assert node.score == 3

    result = skip_list.get_range(1, 2)
    assert len(result) == 2
    for node in result:
        print(node.key)
        print(node.score)
        assert node.score in [1,2]

Level的随机生成

在跳跃表中,每个节点的level数随机按1-5生成并不是很好,可以引入一个算法。在redis中,每个节点的level有1-32层。层数越大的节点越少。具体上,可以这样实现:

代码语言:javascript
复制
import random
import math

def get_random(size):
    # 产生[0-n)的随机数,数越大,则产生的概率越小
    return size - int(math.sqrt(random.randint(0, size*size-1))) -1

count = [0]*32
for i in range(1000000):
    rnd = get_random(32)
    count[rnd] += 1

print(count)
100W 次结果:
[61411, 59880, 57719, 55929, 53847, 51683, 49576, 47808, 45463, 43657, 41902, 40120, 38288, 36274, 34416, 32375, 30376,28179, 26208, 24222, 22481, 20539, 18502, 16698, 14615, 12859, 10536, 8892, 6803, 4925, 2878, 939]
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-12-06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Level的随机生成
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档