python3.6實現跳錶
阿新 • • 發佈:2019-02-18
實現:
使用一個類表示跳錶的節點
#跳躍表節點的類
class SNode:
def __init__(self,key=None,value=None):
#鍵
self.key=key
#index表示陣列中最末的元素
self.maxIndex=-1
#link使用一個數組 存放全部下節點的索引 link[i]表示第i層的索引
self.link=[]
self.value=value
跳錶類 的構造方法
class SkipList :
def __init__(self,size=8,larger=65535):
#深度
self.size = size
'''
跳躍表的深度和你的資料有關 大約為 log n
'''
#尾節點指標
self.tial=SNode()
#頭結點指標 存放頭結點
self.head=SNode()
#存放在插入和刪除操作中 每一個鏈上遇到的最後節點
self.last=[]
self.tial.key=larger#表示尾節點
self.head.key=-65535#表示節點
#頭結點的全部指標指向尾節點
for i in range(self.size):
self.head.link.append(self.tial)
self.MAX_RAND=self.size
由於跳錶的節點高度是隨機的 要用一個函式 確定
#隨機分配層數 但是不會超過最大層數
def randomDispenseLevel(self):
level=1
while random.randint(0 ,1)==1:
level+=1
return level if level<=self.MAX_RAND else self.MAX_RAND
last陣列用來儲存動態操作(插入和刪除) 某節點後該節點前面的節點
#獲取last數組裡的值
def getLast(self,data):
#print(data)
num = self.size - 1 #陣列儲存時是自底向上 查詢是自頂向下 所以num表示層數
p = self.head
while num >= 0:
while p.link[num].key <data:#和進行一次查詢一樣 如果小於,說明這個節點是待動態操作節點的前一個節點
p = p.link[num]
num -= 1
self.last.append(p if p != None else self.head)#如果節點不是空就加入last裡
return self.last[len(self.last)-1]#p指向最底層的節點
查詢
def find(self,data):
FLAGE=False#標準位 查詢是否成功
temp=self.head #temp開始存放頭指標
i=self.size-1 #i是最大長度-1 因為是從上往下找
while i>=0: #如果沒有越界
if temp.link[i].key==self.tial.key:#如果到達最後的尾指標 說明當前層沒有要找的節點
i-=1
continue
if temp.link[i].key<data:#如果小於待查詢的資料 說明要將節點切換到下一個節點
temp=temp.link[i]
i=len(temp.link)-1
elif temp.link[i].key==data:#如果相等說明找到了
FLAGE=True
return temp.link[i],FLAGE
else:
if i>0:#如果沒找到 切沒有到最後一層 直接下降一層
i-=1
else:
return temp,FLAGE
return temp,FLAGE
插入
def insert(self,key,value=None):
'''
插入的方法
:param key: 待插入資料的 鍵值對
:return: true or false
'''
curNode=self.getLast(key) # 獲取last陣列的值
if curNode.key!=key: #flag為false說明沒有相同元素
#獲得層數
lev=self.randomDispenseLevel()
#構造一個新節點
newNode=SNode(key,value)
count=self.size-1 #控制節點的變化
num=0 #控制節點裡面數組的具體號
'''
為什麼count是從大到小 num是從小到大
因為查詢是從上往下 所以last陣列存放是從上往下
但是每個節點的link陣列存放節點物件是從下往上
'''
while num<=lev-1:
length=len(self.last[count].link)-1#獲取不同的節點link陣列長度
while num<=length:
if num>lev-1:
break
newNode.link.append(self.last[count].link[num])#插入新節點 last裡的節點指向new節點
self.last[count].link[num] = newNode#新節點變成last裡元素的下一個節點
num+=1
count -= 1 #節點切換
self.last=[]#必須插入一次後必須將last重新變為空 因為list的append方法會不斷新增新的元素
return True
return False
刪除
def remove(self,key):
'''
刪除的思路
先進行一次find 如果存在就刪除
先獲得last陣列
然後進行刪除
:param key: 待刪除資料的鍵
:return:
'''
temp,flag=self.find(key)
if flag:#如果存在這個鍵
self.getLast(key)#獲取last陣列的值
length=len(temp.link)-1#獲取待刪除陣列鍵的長度
count = self.size - 1 # 控制last數組裡節點的變化
num = 0 # 6控制待刪除節點裡面數組的具體號
while num<=length:
self.last[count].link[num]=temp.link[num]
num+=1
count-=1
self.last=[]#必須插入一次後必須將last重新變為空 因為list的append方法會不斷新增新的元素
return True
return False
輸出跳錶
#順序輸出跳躍表
def outpute(self):
i = self.size - 1
while i>=0:
# i是最大長度-1 因為是從上往下找
p=self.head
if p.link==None or p.link[i].key == self.tial.key: # 如果到達最後的尾指標 說明當前層沒有要找的節點
print('head----->tial')
i -= 1
continue
else:
print('head',end='--->')
while True:
if p.link==None or p.link[i].key == self.tial.key:
break
print(p.link[i].key, end='--->')
p=p.link[i]
print('tail')
i -= 1
測試方法
if __name__=='__main__':
s=SkipList(size=5)
x=[1,2,3,4,5,6,7,8,9]
for i in x:
s.insert(i,i)
print('最開始的情況')
s.outpute()
print('刪除4')
print(s.remove(4))
s.outpute()
print('插入4')
print(s.insert(4))
s.outpute()
print('刪除3')
print(s.remove(3))
s.outpute()
print('刪除5')
print(s.remove(5))
s.outpute()
print('刪除1')
print(s.remove(1))
s.outpute()
執行結果
最開始的情況
head--->4--->6--->tail
head--->3--->4--->6--->tail
head--->3--->4--->6--->tail
head--->2--->3--->4--->6--->tail
head--->1--->2--->3--->4--->5--->6--->7--->8--->9--->tail
刪除4
True
head--->6--->tail
head--->3--->6--->tail
head--->3--->6--->tail
head--->2--->3--->6--->tail
head--->1--->2--->3--->5--->6--->7--->8--->9--->tail
插入4
(<Algorithm.List.SNode.SNode object at 0x00000244AE32C320>, False)
head--->6--->tail
head--->3--->6--->tail
head--->3--->6--->tail
head--->2--->3--->6--->tail
head--->1--->2--->3--->5--->6--->7--->8--->9--->tail
刪除3
True
head--->6--->tail
head--->6--->tail
head--->6--->tail
head--->2--->6--->tail
head--->1--->2--->5--->6--->7--->8--->9--->tail
刪除5
True
head--->6--->tail
head--->6--->tail
head--->6--->tail
head--->2--->6--->tail
head--->1--->2--->6--->7--->8--->9--->tail
刪除1
True
head--->6--->tail
head--->6--->tail
head--->6--->tail
head--->2--->6--->tail
head--->2--->6--->7--->8--->9--->tail