原理简介
说到怎样在一组数据中快速的查找某个元素,我们最先想到的肯定是二分查找,而使用二分查找就要构建一个顺序排列线性表结构,虽然加快了查询的效率,但是增、删、改的效率大大下降。而链表类的数据结构增删改操作效率是很高的,因为它只需要更改相应的指针即可,而不像数组类的顺序线性表增删改操作需要变更内存空间。我们也知道链表的查询效率很低,那么有没有一种能提高链表查询效率的算法呢?

上图是一个最常见的有序单链表,,最普遍的查询就是迭代,这是一个时间复杂度为O(n)的操作,从而导致链表的增删改的效率也随之下降。由此跳表就出生了,它是一种针对于有序链表的基于二分查找思想的查询算法,它的时间复杂度趋近于logn,可以大大提升链表的查询效率。
那么跳表具体是怎么实现的呢?还是看上图中的有序单链表,假设我现在要查找的元素是10,那么传统的迭代至少要查找8次才能找到对应的元素,依据二分查找的思想有一大部分的数据查找是可以避免的,假设我比较完一不符合之后按序直接比较9,那么只需在比较一次就能查找到10,可以避免很多无意义的查询。那么链表怎么实现这种操作呢?

上图就是一个跳表的简易图,就是通过多级指针来减少无意义的查询,就是1的元素不仅有一个指针指向3,也有可能有一个指针指向9或者其他的,从而达到一种趋近于二分查找思想的算法。
实现
节点类
class Node:
"""
跳表节点类
forwards列表就是之前说的多级指针
"""
def __init__(self, level, key=None, value=None):
self.key = key
self.value = value
self.forwards = [None] * level
跳跃链表
定级
怎么确定新增时的级别呢?答案就是抛硬币,就是随机数来确定新增的级别。
MAX_LEVEL = 16
def random_level():
level = 0
for i in range(-1, MAX_LEVEL):
level += random.randint(0, 1)
return level
完整代码
class SkipList:
"""
跳表
"""
def __init__(self):
self.head = Node(level=MAX_LEVEL)
self.level = 0
self.size = 0
def insert(self, key, value):
"""
新增
找出每一级要更新的节点
通过随机数确定更新的级数
如果大于当前跳表级别 跳表扩张一级
:param key: key
:param value: value
:return: insert res
"""
if key is None:
return False
update = [None] * MAX_LEVEL
try:
for i in range(self.level - 1, -1, -1):
q = self.head
while q.forwards[i] and q.forwards[i].key <= key:
q = q.forwards[i]
if q and q.key == key:
return False
update[i] = q
ins_level = random_level()
if ins_level > self.level:
update[self.level] = self.head
ins_level = self.level + 1
self.level = ins_level
ins_node = Node(level=ins_level, key=key, value=value)
for i in range(ins_level):
ins_node.forwards[i] = update[i].forwards[i]
update[i].forwards[i] = ins_node
self.size += 1
except Exception as e:
print(e)
return False
return True
def find(self, key):
"""
寻找某个key对应value
:param key: key
:return: value
"""
if not key:
return None
p = self.head
for i in range(self.level - 1, -1, -1):
while p.forwards[i] and p.forwards[i].key <= key:
if p.forwards[i].key == key:
return p.forwards[i].value
p = p.forwards[i]
return None
def delete(self, key):
"""
同新增 依然是要找到对应节点的前驱节点
:param key: key
:return: t/f
"""
if not key:
return False
update = [None] * MAX_LEVEL
q = None
for i in range(MAX_LEVEL - 1, -1, -1):
q = self.head
while q.forwards[i] and q.forwards[i].key < key:
q = q.forwards[i]
update[i] = q
del_node = q.forwards[0]
del q
if del_node and del_node.key == key:
for i in range(self.level):
if update[i] and update[i].forwards[i] == del_node:
del_node.forwards[i] = None
update[i].forwards[i] = update[i].forwards[i].forwards[i]
del del_node
for i in range(self.level - 1, -1, -1):
if self.head.forwards[i] is None:
self.level -= 1
self.size -= 1
return True
else:
return False
def print_all(self):
for i in range(self.level - 1, -1, -1):
p = self.head
while p.forwards[i]:
print(str(p.forwards[i].key) + "-->", end="")
p = p.forwards[i]
print('\r\n')
1530

被折叠的 条评论
为什么被折叠?



