python資料結構 大頂堆和小頂堆

2022-03-10 16:53:00 字數 3395 閱讀 5340

class heap:

"""二叉堆的實現 小頂堆"""

def __init__(self):

self.heaplist = [0] # 預設乙個 0 做佔位,使得根節點的索引在 1 上

self.currentsize = 0 # 最大節點的索引位置

def perup(self, i):

"""將小節點逐步上公升"""

while i // 2 > 0:

if self.heaplist[i] < self.heaplist[i // 2]:

self.heaplist[i], self.heaplist[i // 2] = self.heaplist[i // 2], self.heaplist[i]

i = i // 2

def insert(self, k):

"""插入節點"""

self.currentsize += 1

self.perup(self.currentsize)

def minchild(self, i):

"""獲取左右兩個子節點裡較小的那個子節點的索引"""

if i * 2 + 1 > self.currentsize: # 右子節點超出節點數量

return i * 2

else:

if self.heaplist[i * 2] < self.heaplist[i * 2 + 1]:

return i * 2

else:

return i * 2 + 1

def perdown(self, i):

"""將節點下沉到合適位置"""

while (i * 2) <= self.currentsize: # 說明有子節點

mc = self.minchild(i)

if self.heaplist[i] > self.heaplist[mc]:

self.heaplist[i], self.heaplist[mc] = self.heaplist[mc], self.heaplist[i]

i = mc

def delmin(self):

"""刪除小節點"""

retval = self.heaplist[1] # 刪除索引位置為 1 的節點

self.heaplist[1] = self.heaplist[self.currentsize]

self.heaplist.pop()

self.currentsize -= 1

self.perdown(1)

return retval

def buildheap(self, alist):

i = len(alist) // 2

self.currentsize = len(alist)

self.heaplist += alist[:]

while i > 0:

self.perdown(i)

i -= 1

class heaplist(object):

"""大頂推"""

def __init__(self):

self.heaplist = [0]

self.size = 0

def buildheap(self, alist):

i = len(alist) // 2

self.size = len(alist)

self.heaplist += alist[:]

while i > 0:

self.percdown(i)

i -= 1

def percup(self, i):

while i // 2 > 0:

if self.heaplist[i] > self.heaplist[i // 2]:

self.heaplist[i], self.heaplist[i // 2] = self.heaplist[i // 2], self.heaplist[i]

i //= 2

def insert(self, k):

self.size += 1

self.percup(self.size)

def maxchild(self, i):

if i * 2 + 1 > self.size:

return i * 2

else:

if self.heaplist[i * 2] > self.heaplist[i * 2 + 1]:

return i * 2

else:

return i * 2 + 1

def percdown(self, i):

while i * 2 <= self.size:

mc = self.maxchild(i)

if self.heaplist[i] < self.heaplist[mc]:

self.heaplist[i], self.heaplist[mc] = self.heaplist[mc], self.heaplist[i]

i = mc

def delmax(self):

retval = self.heaplist[1]

self.heaplist[1] = self.heaplist[self.size]

self.size -= 1

self.heaplist.pop()

self.percdown(1)

return retval

# 採用大頂堆的方式,製作容量為 k 的大頂堆,向堆中新增元素時,比堆頂值小,就彈出堆頂,並將此元素新增進堆。這就保證,最後遍歷完成後,

# 我們獲得了比堆頂小的 k-1 個最小值

# 時間複雜度 o(nlogk) 因為只維護 k 大小的堆

class solution:

def getleastnumbers(self, arr, k):

if k == 0:

return

heaplist = heaplist()

heaplist.buildheap(arr[:k])

for i in arr[k: ]:

if i < heaplist.heaplist[1]:

heaplist.delmax()

heaplist.insert(i)

return heaplist.heaplist[1:]

if __name__ == '__main__':

solution = solution()

arrlist = [1, 2, 3, 4, 5, 6, 7, 8]

res = solution.getleastnumbers(arrlist, 3)

print(res)

資料結構 堆,小頂堆,大頂堆,堆排序

堆是什麼?堆是一種特殊的完全二叉樹,就像下面這棵樹一樣 這棵樹有乙個很顯著的特點,那就是所有父結點都要比子結點要小。符合這樣要求的完全二叉樹我們成為 最小堆 反之,如果所有父結點都要比子結點大,這樣的完全二叉樹被稱為 最大堆 如果我們現在要刪除掉最小的數字,並重新插入乙個數字,再從中找出最小的數字。...

資料結構 佇列 雙端佇列 小頂堆 大頂堆

queue 佇列 特點 先進先出 q.push num 從後面進佇列 q.pop 從前面出佇列 q.front 讀取佇列最前面的元素 q.back 讀取佇列最後面的元素 deque 雙端佇列 特點 兩端都可以出進 q.push front num 從前面進佇列 q.push back num 從後面...

資料流中的中位數(大頂堆和小頂堆)

如何得到乙個資料流中的中位數?如果從資料流中讀出奇數個數值,那麼中位數就是所有數值排序之後位於中間的數值。如果從資料流中讀出偶數個數值,那麼中位數就是所有數值排序之後中間兩個數的平均值。例如,2,3,4 的中位數是 3 2,3 的中位數是 2 3 2 2.5 設計乙個支援以下兩種操作的資料結構 vo...