最新做了一些题,碰巧看到一道题是实现一个跳表, 对 跳表 早有耳闻,从 ES, Redis 的一些资料中隐约看到过这个名字,以前粗略了解了一下跳表的接口和复杂度,觉得是个小平衡树,真正学习后发现它比平衡树简单多了,但是性能却不差平衡树,真是一种代码性价比极高的数据结构。
看别人题解实现跳表代码很少,觉得是我上我也行的程度。就找了几篇文章学习,自己动手实现,写完一对比,行也不行,行的是功能都实现了,不行的是别人的版本速度比我的版本快10倍!而且代码巧妙又优雅。
先贴一下我的实现
import randomMAX_LEVEL = 16class Node:def __init__(self, val=0):self.val = valself.right = Noneself.down = Nonedef get_level():# 1/2 是最下层,1/4是第二层。。。。init_num = 1p = 1 / 2while random.random() < p and init_num < MAX_LEVEL:init_num += 1return init_numclass Skiplist:def __init__(self):self.left = [Node(-1) for _ in range(16)]for i in range(15):self.left[i].down = self.left[i + 1]self.head = self.left[0]def search(self, target: int) -> bool:prv = self.headwhile prv:if prv.val == target:return Trueelif not prv.right or prv.right.val > target:prv = prv.downelse:prv = prv.rightreturn Falsedef add(self, num: int) -> None:level = get_level() # 3 self.left[13]print(level)level_head = self.headfor _ in range(MAX_LEVEL - level):level_head = level_head.downself._add(level_head, num)def _add(self, prv_head, num):while prv_head:if not prv_head.right or num < prv_head.right.val:right = prv_head.rightnode = Node(num)prv_head.right = nodenode.right = rightnode.down = self._add(prv_head.down, num)return nodeelse:prv_head = prv_head.rightdef erase(self, num: int) -> bool:is_removed = Falseprv = self.headwhile prv:if not prv.right or prv.right.val > num:prv = prv.downelif prv.right.val == num:prv.right = prv.right.rightprv = prv.downis_removed = Trueelse:prv = prv.rightreturn is_removeddef print(self):_list = [[] for _ in range(MAX_LEVEL)]for i in range(MAX_LEVEL):cur = self.left[i]while cur:_list[i].append(cur.val)cur = cur.rightprint(_list[i], len(_list[i]))sk = Skiplist()for i in range(1, 100):sk.add(i)print(sk.erase(0))sk.print()
别人的实现
import randomclass Node:def __init__(self, val=0):self.val = valself.right = Noneself.down = Noneclass Skiplist:def __init__(self):self.left = [Node(-1) for _ in range(16)]self.right = [Node(20001) for _ in range(16)]for i in range(15):self.left[i].right = self.right[i]self.left[i].down = self.left[i + 1]self.right[i].down = self.right[i + 1]self.left[-1].right = self.right[-1]self.head = self.left[0]def search(self, target: int) -> bool:cur = self.headwhile cur:if cur.right.val > target:cur = cur.downelif cur.right.val < target:cur = cur.rightelse:return Truereturn Falsedef add(self, num: int) -> None:cur = self.headstack = []while cur:if cur.right.val >= num:stack.append(cur)cur = cur.downelse:cur = cur.rightpre = Nonewhile stack:cur = stack.pop()node = Node(num)node.right = cur.rightcur.right = nodeif pre:node.down = prepre = nodeif random.randint(0, 1):breakdef erase(self, num: int) -> bool:cur = self.headis_removed = Falsewhile cur:if cur.right.val >= num:if cur.right.val == num:is_removed = Truecur.right = cur.right.rightcur = cur.downelse:cur = cur.rightreturn is_removeddef print(self):_list = [[] for _ in range(16)]for i in range(16):cur = self.left[i]while cur:_list[i].append(cur.val)cur = cur.rightprint(_list[i], len(_list[i]))sk = Skiplist()for i in range(1, 100):sk.add(i)print(sk.search(99))sk.print()
