跳錶(Skip List)是對鏈表改造後的動態數據結構,利用空間換時間的思想,建立多級索引來提高查找、插入、刪除操作的效率。
一層一層索引有點類似二分查找這種分而治之的思想。
在跳錶中查詢一個數據的時間複雜度是O( log n ),空間複雜度是O( n )。
跳錶通過隨機函數來維護平衡性,即索引大小與原始鏈表大小之間的平衡,不至於性能過度退化,有效平衡執行效率和內存消耗。通過隨機函數,來決定將這個結點插入到哪幾級索引中,比如隨機函數生成了值K,那就將結點添加到第一級到第K級這K級索引中。
以下是用python3的具體實現。
from typing import Optional
import random
class ListNode:
def __init__(self, data: Optional[int] = None):
self._data = data
self._forwards = []
class SkipList:
_MAX_LEVEL = 16
def __init__(self):
self._level_count = 1
self._head = ListNode()
self._head._forwards = [None] * type(self)._MAX_LEVEL
def find(self, value: int) -> Optional[ListNode]: # 查找
p = self._head
for i in range(self._level_count - 1, -1, -1):
while p._forwards[i] and p._forwards[i]._data < value:
p = p._forwards[i]
return p._forwards[0] if p._forwards[0] and p._forwards[0]._data == value else None
def insert(self, value: int): # 插入
level = self._random_level()
if self._level_count < level:
self._level_count = level
new_node = ListNode(value)
new_node._forwards = [None] * level
update = [self._head] * level
p = self._head
for i in range(level - 1, -1, -1):
while p._forwards[i] and p._forwards[i]._data < value:
p = p._forwards[i]
update[i] = p
for i in range(level):
new_node._forwards[i] = update[i]._forwards[i]
update[i]._forwards[i] = new_node
def delete(self, value: int): 刪除
update = [None] * self._level_count
p = self._head
for i in range(self._level_count - 1, -1, -1):
while p._forwards[i] and p._forwards[i]._data < value:
p = p._forwards[i]
update[i] = p
if p._forwards[0] and p._forwards[0]._data == value:
for i in range(self._level_count - 1, -1, -1):
if update[i]._forwards[i] and update[i]._forwards[i]._data == value:
update[i]._forwards[i] = update[i]._forwards[i]._forwards[i]
def _random_level(self, p: float = 0.5) -> int: # 隨機函數
level = 1
while random.random() < p and level < type(self)._MAX_LEVEL:
level += 1
return level
def __repr__(self) -> str:
values = []
p = self._head
while p._forwards[0]:
values.append(str(p._forwards[0]._data))
p = p._forwards[0]
return "->".join(values)
if __name__ == "__main__":
l = SkipList()
for i in range(10):
l.insert(i)
print(l)
p = l.find(8)
print(p._data)
l.delete(4)
print(l)