日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

heap python_数据结构-堆(Heap) Python实现

發布時間:2025/3/15 python 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 heap python_数据结构-堆(Heap) Python实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

堆(Heap)可以看成近似完全二叉樹的數組,樹中每個節點對應數組中一個元素。除了最底層之外,該樹是完全充滿的,最底層是從左到右填充的。

堆包括最大堆和最小堆:最大堆的每一個節點(除了根結點)的值不大于其父節點;最小堆的每一個節點(除了根結點)的值不小于其父節點。

本文以最大堆為例,先直觀感受一下堆的樣子:

圖片來源

最大堆

樹中節點內的值表示存儲的值,節點旁邊的值表示該節點在數組中的下標。

觀察上圖不難發現,對于一個給定節點的下標i,其父節點、左孩子、右孩子的下標為:

parent(i): (i + 1) // 2 - 1

left(i): i * 2 + 1

right(i): i * 2 + 2

其中“//”表示除法后只取整數部分。

對于一個給定的數組,如何轉化為堆呢?

對于一個任意節點,如果該節點大于左孩子和右孩子,則該節點無需移動。否則,和左右孩子中較大的那個交換位置,于是該節點滿足大于左右孩子了,但是剛被交換了的孩子節點需要繼續比較它的左右孩子......整個過程遞歸進行下去,我們可以輕松計算出:對于根節點,在進行轉化成堆的過程中,最多需要交換h次(h為樹的高度),對于樹種的每個節點,如果都進行此操作,則整個過程的時間復雜度為:O(nlogn)。(n為節點數,logn≈h)

代碼如下:

def heapify(self):

for i in range((len(self.heap) + 1) // 2 - 1, -1, -1):

self.max_heapify_top(i)

def max_heapify_top(self, i):

"""

從上到下

O(logn)

"""

left = i * 2 + 1

right = i * 2 + 2

if left < len(self.heap) and self.heap[left] > self.heap[i]:

largest = left

else:

largest = i

if right < len(self.heap) and self.heap[right] > self.heap[largest]:

largest = right

if largest != i:

self.heap[largest], self.heap[i] = self.heap[i], self.heap[largest]

self.max_heapify_top(largest)

以上代碼中heapify函數從(len(self.heap) + 1) // 2 - 1到0進行遍歷,是因為樹中的葉子節點沒有孩子,因此可以看成滿足堆的性質,所以無需進行heapify,所以從非葉子節點開始遍歷,節約時間。

如何從堆中彈出和插入元素呢?

先說彈出。由于是最大堆,因此每次彈出需要彈出最大的元素,那就是根節點,如何彈出后還保持堆的性質呢。具體做法是:先將樹中根節點和最后一個節點交換位置,對應數組中就是第一個元素和最后一個元素交換位置,然后彈出最后一個元素,在對交換位置后的根節點進行heapify,這樣彈出了最大元素,同時也保持了堆的性質。

代碼如下:

def pop(self):

"""

O(logn)

"""

self.heap[0], self.heap[len(self.heap) - 1] = self.heap[len(self.heap) - 1], self.heap[0]

value = self.heap.pop()

self.max_heapify_top(0)

return value

插入元素。

先將元素放在樹的末尾,也是數組的末尾,再按照自下而上的順序依次比較與父節點的大小關系,自下而上進行heapify。

代碼如下:

def push(self, value):

"""

O(logn)

"""

self.heap.append(value)

self.max_heapify_button(len(self.heap) - 1)

def max_heapify_button(self, i):

"""

從下到上

O(logn)

"""

parent = (i + 1) // 2 - 1

if parent >= 0 and self.heap[parent] < self.heap[i]:

smallest = parent

else:

smallest = i

if smallest != i:

self.heap[smallest], self.heap[i] = self.heap[i], self.heap[smallest]

self.max_heapify_button(smallest)

整個堆的實現代碼為:

class Heap:

def __init__(self, heap=[]):

self.heap = heap

def heapify(self):

for i in range((len(self.heap) + 1) // 2 - 1, -1, -1):

self.max_heapify_top(i)

def max_heapify_top(self, i):

"""

從上到下

O(logn)

"""

left = i * 2 + 1

right = i * 2 + 2

if left < len(self.heap) and self.heap[left] > self.heap[i]:

largest = left

else:

largest = i

if right < len(self.heap) and self.heap[right] > self.heap[largest]:

largest = right

if largest != i:

self.heap[largest], self.heap[i] = self.heap[i], self.heap[largest]

self.max_heapify_top(largest)

def max_heapify_button(self, i):

"""

從下到上

O(logn)

"""

parent = (i + 1) // 2 - 1

if parent >= 0 and self.heap[parent] < self.heap[i]:

smallest = parent

else:

smallest = i

if smallest != i:

self.heap[smallest], self.heap[i] = self.heap[i], self.heap[smallest]

self.max_heapify_button(smallest)

def pop(self):

"""

O(logn)

"""

self.heap[0], self.heap[len(self.heap) - 1] = self.heap[len(self.heap) - 1], self.heap[0]

value = self.heap.pop()

self.max_heapify_top(0)

return value

def push(self, value):

"""

O(logn)

"""

self.heap.append(value)

self.max_heapify_button(len(self.heap) - 1)

再說堆排序呢?對于一個任意的數組,進行構建堆之后,再按照順序依次彈出堆中的元素,便得到了有序的數組。更神奇的是,在數組末尾添加一個指針,便可實現數組的原地排序(不需要額外空間)。堆排序的時間復雜度為:O(nlogn),空間復雜度為:O(1)

總結

以上是生活随笔為你收集整理的heap python_数据结构-堆(Heap) Python实现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。