常用排序演算法 堆排序

2022-09-16 00:09:19 字數 1693 閱讀 2378

堆:分為大根堆和小根堆

大根堆:一棵完全二叉樹,滿足任意一節點都比其孩子節點大。

小根堆:一棵完全二叉樹,滿足任意一節點都比其孩子節點小。

堆排序流程: 

構造堆得到堆頂元素,為最大元素

去掉堆頂,將堆的最後乙個元素放到堆頂,然後調整重新使堆有序

堆頂元素為第二大的元素

重複第三步直到堆變空

例如以[4, 5, 3, 6, 1, 2 ]為例:

準備知識:

在以順序儲存的完全二叉樹中,父子節點的關係(下標):

父節點和左孩子:左孩子下標 = 父節點下標 * 2 + 1

父節點和右孩子:右孩子下標 = 父節點下標 * 2 + 2

子節點和父節點: 父節點下標 = (子節點下標 - 1)  // 2

最後乙個非葉子節點:n // 2 -1

def sift(nums, low, high):

"""調整堆,使堆有序

:param nums: list

:param low: 根節點

:param high: 尾節點(樹的最後乙個)

:return:

"""temp = nums[low]

i = low

j = 2 * i + 1

while j <= high: # 當前i位置為葉子節點, j超過high了

# 找更大的子節點

if j + 1 <= high and nums[j+1] > nums[j]: #

j = j + 1

if temp < nums[j]:

nums[i] = nums[j]

i = j

j = 2 * i + 1

else: # temp 大於兩個子節點

break

nums[i] = temp

def heap_sort(nums):

# 建堆

l = len(nums)

for i in range(l//2-1, -1, -1):

# i是建堆時要調整的子樹的根節點下標

sift(nums, i, l-1)

for i in range(l - 1, -1, -1):

# 當前的high值

nums[i], nums[0] = nums[0], nums[i]

sift(nums, 0, i-1)

python內建模組heapq幫我們實現了堆排序,內建函式用的是小根堆,上面的**是大根堆,差別不大,heapq模組主要包括三個函式:

heapify(list) 建小根堆   把傳入的list變成小根堆

import heapq

nums = [3, 2, 1, 0, 6]

heapq.heapify(nums)

print(nums)

# [0, 2, 1, 3, 6]

print(nums)

# [0, 2, 1, 3, 6, 4]

# 0# 1

# 2

排序演算法 堆排序

1 什麼是堆 首先它是一顆完全二叉樹,並且父結點的值大於子節點的值 最大堆 或父結點的值小於子結點的值 最小堆 小根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最小者的堆稱為小根堆,又稱最小堆。大根堆 根結點 亦稱為堆頂 的關鍵字是堆裡所有結點關鍵字中最大者,稱為大根堆,又稱最大堆。2 堆...

排序演算法 堆排序

花了一晚上時間研究堆排序,這個排序困擾了哥很久,終於搞清楚了。一 堆的定義 1.父結點的鍵值總是大於或等於 小於或等於 任何乙個子節點的鍵值 2 每個結點的左子樹和右子樹都是乙個二叉堆 都是最大堆或最小堆 二 已知結點 i 則它的子結點 為2 i 1 與 2 i 2 父節點為 i 1 2 三 堆排序...

排序演算法 堆排序

由於不經常使用,之前學習看過的演算法都給忘了。現在把他們寫下來,記錄下來,以方便以後查閱。本篇文章的 即為堆排序的 主函式中是對輸入檔案中的序列進行排序,並將結果輸出到乙個檔案中。這是一種形式類似於google codejam的測試方法。include include using namespace...