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