温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

python怎么实现跳表SkipList

发布时间:2022-03-29 17:19:34 来源:亿速云 阅读:210 作者:iii 栏目:移动开发

本篇内容介绍了“python怎么实现跳表SkipList”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

跳表

跳表,又叫做跳跃表、跳跃列表,在有序链表的基础上增加了“跳跃”的功能,由William Pugh于1990年发布,设计的初衷是为了取代平衡树(比如红黑树)。
Redis、LevelDB 都是著名的 Key-Value 数据库,而Redis中 的 SortedSet、LevelDB 中的 MemTable 都用到了跳表。
对比平衡树,跳表的实现和维护会更加简单,跳表的搜索、删除、添加的平均时间复杂度是 O(logn)。
跳表的结构如图所示:

python怎么实现跳表SkipList

可以发现,对于一个节点Node,其含有多个next指针,不同索引的next分别代表不同层次的下一个节点,下次是节点类Node的python定义:

class Node():      def __init__(self,key,value,level):          """          :param level:每个node对应的nexts层数不同          """          self.key=key          self.value=value          self.nexts=[None]*level#节点类型next指针,初始值为空      def __str__(self):          #return "[key:"+str(self.key)+", value:"+str(self.value)+" len:"+str(len(self.nexts))+"]"          return "["+str(self.key)+","+str(self.value)+","+str(len(self.nexts))+"]"

关于添加、删除、查找见一下完整代码:

""" 跳表 Skip List ,其初衷是为了替代红黑树 """ import random import mkl_random import time class SkipList():     def __init__(self):         #头节点不存储任何数据         self.MAX_LEVEL = 32  # 最大level层数         self.__first=SkipList.Node(None, None, self.MAX_LEVEL)#头节点         self.__level=0#实际的level层数         self.__size=0#Jiedian个数         self.__p=0.25#用于生成添加节点时的随机level         return     class Node():         def __init__(self,key,value,level):             """             :param level:每个node对应的nexts层数不同             """             self.key=key             self.value=value             self.nexts=[None]*level         def __str__(self):             #return "[key:"+str(self.key)+", value:"+str(self.value)+" len:"+str(len(self.nexts))+"]"             return "["+str(self.key)+","+str(self.value)+","+str(len(self.nexts))+"]"     def get(self,key):         """         :param key:         :return: key对应的value         """         self.keyCheck(key)         node=self.__first         for level in range(self.__level - 1,-1,-1):             #在该层查找,key大于节点的key向前查找             while node.nexts[level] and node.nexts[level].key<key:                 node=node.nexts[level]             if node.nexts[level] and node.nexts[level].key==key:#相等则找到,否则向下寻找                 return node.nexts[level].value         return None     def put(self,key,value):         """         return:原来的value,原来不存在key则为空         """         self.keyCheck(key)         prev=[None]*self.__level         node=self.__first         for i in range(self.__level - 1, -1, -1):             while node.nexts[i] and node.nexts[i].key<key:                 node=node.nexts[i]             if node.nexts[i] and node.nexts[i].key==key:                 oldValue=node.nexts[i].value                 node.nexts[i].value=value                 return oldValue             prev[i]=node#保存当前level小于key的node         newLevel=self.randomLevel()         newNode=SkipList.Node(key,value,newLevel)         for i in range(newLevel):             if i<self.__level:                 newNode.nexts[i]=prev[i].nexts[i]                 prev[i].nexts[i]=newNode             else:                 self.__first.nexts[i]=newNode         self.__size+=1         self.__level=max(self.__level, newLevel)         return None     def remove(self,key):         """         :return: 节点对应的value值,不存在则返回None         """         self.keyCheck(key)         prev=[None]*self.__level         node=self.__first         flag=False#该节点是否被查找到         for i in range(self.__level - 1, -1, -1):             while node.nexts[i] and node.nexts[i].key<key:                 node=node.nexts[i]             if node.nexts[i].key==key:                 flag=True             prev[i]=node         if not flag:             return None         removedNode=node.nexts[0]#需要被删除的节点         for i in range(len(removedNode.nexts)):#该nexts一定小于等于prev的长度             prev[i].next[i]=removedNode.nexts[i]         self.__size-=1         newLevel=self.__level         while newLevel>0 and not self.__first.nexts[newLevel - 1]:             newLevel-=1         self.__level=newLevel         return removedNode.value     def keyCheck(self, key):         """         限制传入key不能为空         """         if key!=0 and not key:             raise AttributeError("key can not be None")     def size(self):         return self.__size     def isEmpty(self):         return self.__size == 0     def randomLevel(self):#生成一个随机的层数         level=1         while mkl_random.rand()<self.__p and level<self.MAX_LEVEL:             level+=1         return level     def __str__(self):         result=""         for i in range(self.__level - 1, -1, -1):             result+=str(i)             node = self.__first             while node.nexts[i]:                 result+=str(node.nexts[i])                 node=node.nexts[i]             result+=" "         print("level:"+str(self.__level))         return result     def showFirst(self):         for item in self.__first.nexts:             print(item,end=" ")         print() def timeCalculate(container, size:int):     begin=time.time()     for i in range(size):         if isinstance(container,dict):             container[i]= i * 3         else:             container.put(i, i * 3)     error_count = 0     for i in range(size):         if container.get(i) != i * 3:             #print("wrong " + str(i) + ":" + str(skipList.get(i)))             error_count+=1     end=time.time()     print(type(container))     print(f"error rate:{float(error_count) / size:0.5f}")     print(f"time cost:{float(end-begin)*1000:0.3f} ms") if __name__=="__main__":     timeCalculate({},1000000)     timeCalculate(SkipList(),10000)

“python怎么实现跳表SkipList”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI