美文网首页
跳跃表python实践

跳跃表python实践

作者: 钢筋铁骨 | 来源:发表于2020-04-14 15:43 被阅读0次

redis的zset常用场景:
统计日活;打赏排行榜;天梯榜等
zset底层基于跳跃表实现

跳跃表代码实现,练习版

import random
random.seed(1)
MAX_LEVEL = 4


def randomLevel():
    """
    跳表的节点高度计算函数
    """
    k = 0
    while random.randint(0, 1):
        k += 1
    k = k if k < MAX_LEVEL else MAX_LEVEL
    return k


def travel(skiplist):
    """
    遍历跳表,当成二维数组来思考
    :param skiplist:
    :return:
    """
    head = skiplist.head # head负责往下走
    print ("遍历跳表开始")
    while head:
        level_str = 'header'
        current = head # current负责往右走
        while current.right:
            current = current.right
            level_str += " -> %s" % (current.key)
        print (level_str)
        head = head.down
    print ("遍历跳表结束")


class Node(object):
    def __init__(self, key, value=None, extra_data={}, level=0):
        self.key = key
        self.value = value
        self.extra_data = extra_data
        self.level = level
        self.right = None
        self.down = None


class SkipList(object):

    def __init__(self):
        self.head = Node(float('-inf'))
        self.head.right = Node(float('inf'))

    def search(self, target):
        """未验证"""
        current = self.head
        while current:
            if current.key < target <= current.right.key:
                if current.right.key == target:
                    print ("找到节点:", current.key, current.value)
                    return True
                current = current.down
            else:
                current = current.right
        return False

    def find_node(self, target):
        """递归的写法"""
        return self.searchNode(self.head, target)

    def searchNode(self, node, key):
        while key >= node.right.key:
            node = node.right
        if key == node.key:
            print ("找到节点:", node.key, node.extra_data, "层:", node.level)
            return True
        if node.down == None:
            return False
        return self.searchNode(node.down, key)

    def insertNode(self, current, key, value):
        while key >= current.right.key:
            current = current.right
        # 为什么return None,因为跳表的key是唯一的,redis的zset中,如果key已经存在,则根据该元素的score更新排名
        if key == current.key:
            return None
        # 已经走到了level 0层时的逻辑
        if current.down == None:
            node = Node(key, value) # node是插入的节点
            # eg: 在5 --> 15 之间插入Node(10),此时current是Node(5)
            node.right = current.right
            current.right = node
            node.level = current.level
            return node
        downnode = self.insertNode(current.down, key, value)
        if downnode: # 这里处理的是上一层
            node = Node(key)
            node.right = current.right
            current.right = node
            node.down = downnode
            node.level = current.level
            return node
        return None

    def insert(self, key, value):
        k = randomLevel()
        # 如果k和self.head.level都是0时,说明不用建高速,直接在0层添加即可
        # 如果k=1,self.head.level是0时,就需要一层一层网上找,找到最高层,for循环是为了把这几层的边界弄出来
        for l in range(self.head.level+1, k+1):
        #   这个地方画图想象,先获取上一层的左右,最左.right指向最右;
        #   最左.down指向下一层的head(刚好是self.head),然后让self.head爬楼升1
            headleft, headright = Node(float("-inf"), level=l), Node(float("inf"), level=l)
            headleft.right = headright
            headleft.down = self.head
            self.head = headleft
        head = self.head # 跳表最高层的头
        while head.level != k:
            head = head.down
        self.insertNode(head, key, value)
        print ("k=%s, key=%s, value=%s, insert OK" %(k, key, value))

    def erase(self, num):
        current = self.head
        is_removed = False
        while current:
            if current.val < num <= current.right.val:
                if current.right.val == num:
                    current.right = current.right.right
                    is_removed = True
                current = current.down
            else:
                current = current.right
        return is_removed


if __name__ == '__main__':
    skiplist = SkipList()
    skiplist.insert(4, random.randint(1,100))
    skiplist.insert(5, random.randint(1,100))
    skiplist.insert(15, random.randint(1,100))
    skiplist.insert(25, random.randint(1,100))
    skiplist.insert(35, random.randint(1,100))
    print (skiplist.find_node(25))
    print (skiplist.find_node(15))
    travel(skiplist=skiplist)

相关文章

  • 跳跃表python实践

    redis的zset常用场景:统计日活;打赏排行榜;天梯榜等zset底层基于跳跃表实现 跳跃表代码实现,练习版

  • python实现跳跃表(SkipList)

    跳跃表是一种随机化的数据结构,目前开源软件 Redis 和 LevelDB 都有用到它,它的效率和红黑树以及 AV...

  • Redis Sorted-set有序集合的实现原理

    什么是跳跃表?跳跃表

  • 跳跃表

    什么是跳跃表 跳跃表(skiplist)是一种基于有序链表的扩展,简称跳表 时间和空间复杂度 插入的时间复杂度是:...

  • 跳跃表

    跳跃表是一种随机化数据结构,基于并联的链表,其效率可比拟于二叉查找树(对于大多数操作需要O(log n)平均时间)...

  • 跳跃表

    Skip List是一种随机化的数据结构,基于并联的链表,其效率可比拟于二叉查找树.基本上,跳跃列表是对有序的链表...

  • 跳跃表

    最近在看redis源码,其中看到跳跃表的部分。无奈大学期间数据结构学的基本上都快忘没了,在网上找了个介绍跳跃表的两...

  • 跳跃表

    跳跃表是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节点的目的。《Skip l...

  • 跳跃表

    Skip List定义 Skip List 完整实现 下面是跳表的基本操作 节点的创建 列表的初始化列表的初始化需...

  • 跳跃表

    先看下面这个图。 这里的数据结构就是跳跃表。这个结构比较简单,在底层有一个有序链表,链表的两端有一个哨兵结点。在第...

网友评论

      本文标题:跳跃表python实践

      本文链接:https://www.haomeiwen.com/subject/qdrtvhtx.html