堆排序python實現 堆排 python實現堆排

2021-10-11 14:51:22 字數 3496 閱讀 4410

一、堆-完全二叉樹

堆排序是利用堆這種資料結構而設計的一種排序演算法,堆排序是一種選擇排序,它的最壞,最好,平均時間複雜度均為o(nlogn),是不穩定排序

堆排序中的堆有大頂堆、小頂堆兩種。他們都是完全二叉樹

將該堆按照排序放入列表

1. 大頂堆:

所有的父節點的值都比孩子節點大,葉子節點值最小。root 根節點是第乙個節點值最大

2. 小頂堆:

和大頂堆相反,所有父節點值,都小於子節點值,root 根節點是 第乙個節點值最小

二、堆排序

基本思路:將待排序序列構造成乙個大頂堆,此時,整個序列的最大值就是堆頂的根節點。將其與末尾元素進行交換,此時末尾就為最大值。可稱為有序區,然後將剩餘n-1個元素重新構造成乙個堆,估且稱為堆區(未排序)。這樣會得到n個元素的次小值。重複執行,有序區從:1--->n,堆區:n-->0,便能得到乙個有序序列了

2.1 構造大頂堆

在構造有序堆時,開始時只需要掃瞄一半的元素(所有父節點)(length/2-1 --> 0)

因為只有他們才有子節點:3-->2 -->1 -->0

1. 從最後乙個父節點開始,將父節點、他所有的子節點中的最大值交換到父節點。父節點:3

2. 將倒數第二個父節點同理交換,父節點:2

3. 父節點:1

4. 根節點:0

5. 注意很重要:務必注意-承接第3步。

假設根節點值為:10, 當他和兩個子節點70, 80,

父節點和兩子節點中的大的(80)交換後位於父節點2:原來80的位置。

可是他還有子節點,且子節點中的值比根節點大,那就還需要以他為父節點構造一次,與子節點6 值為20交換一次

同理在其他所有父節點的構造中都需要判斷調整

忽略第五步。構造好的的大頂堆如下:

2.2 開始排序

基本思路:將待排序序列構造成乙個大頂堆,此時,整個序列的最大值就是堆頂的根節點。將其與末尾元素進行交換,此時末尾就為最大值。可稱為有序區,然後將剩餘n-1個元素重新構造成乙個堆,估且稱為堆區(未排序)。這樣會得到n個元素的次小值。重複執行,有序區從:1--->n,堆區:n-->0,便能得到乙個有序序列了

每次將堆頂(根節點)最的的元素和堆尾列表最後乙個元素交換,80 和40交換

即上面說的堆區(未排序):n-->0最大元素(根節點),和有序區從:1--->n,最後乙個元素交換

按照上面原理繼續排序,70, 30 交換。然後調整堆

堆頂元素60尾元素20交換後-->調整堆

最後結果

三、python**實現

現在排序這麼乙個序列:list_ = [4, 7, 0, 9, 1, 5, 3, 3, 2, 6]

堆排序 heap_sort

7 09 1 5 3

3 2 6

list_ = [4, 7, 0, 9, 1, 5, 3, 3, 2, 6]

3.2 **實現

def swap(data, root, last):

data[root], data[last] = data[last], data[root]

#調整父節點 與孩子大小, 製作大頂堆

def adjust_heap(data, par_node, high):

new_par_node = par_node

j = 2*par_node +1 #取根節點的左孩子, 如果只有乙個孩子 high就是左孩子,如果有兩個孩子 high 就是右孩子

while j <= high: #如果 j = high 說明沒有右孩子,high就是左孩子

if j < high and data[j] < data[j+1]: #如果這兒不判斷 j < high 可能超出索引

# 乙個根節點下,如果有兩個孩子,將 j 指向值大的那個孩子

j += 1

if data[j] > data[new_par_node]: #如果子節點值大於父節點,就互相交換

data[new_par_node], data[j] = data[j], data[new_par_node]

new_par_node = j #將當前節點,作為父節點,查詢他的子樹

j = j * 2 + 1

else:

# 因為調整是從上到下,所以下面的所有子樹肯定是排序好了的,

#如果調整的父節點依然比下面最大的子節點大,就直接打斷迴圈,堆已經調整好了的

break

# 索引計算: 0 -->1 --->....

# 父節點 i 左子節點:2i +1 右子節點:2i +2 注意:當用長度表示最後乙個葉子節點時 記得 -1

# 即 2i + 1 = length - 1 或者 2i + 2 = length - 1

# 2i+1 + 1 = length 或 2i+2 + 1 = length

# 2(i+1)=length 或 2(i+1)+1 = length

# 設j = i+1 則左子節點(偶數):2j = length 和 右子節點(基數):2j+1 = length

# 2j//2 = j == (2j+1)//2 這兩個的整除是一樣的,所以使用length//2 = j 然後 i + 1 = j

# i = j-1 = length//2 -1 #注意左子節點:2i+1 //2 =i 而右子節點:(2i+2)//2 = i+1

# 從第乙個非葉子節點(即最後乙個父節點)開始,即 list_.length//2 -1(len(list_)//2 - 1)

# 開始迴圈到 root 索引為:0 的第乙個根節點, 將所有的根-葉子 調整好,成為乙個 大頂堆

def heap_sort(lst):

根據列表長度,找到最後乙個非葉子節點,開始循化到 root 根節點,製作 大頂堆

:param lst: 將列表傳入

:return:

length = len(lst)

last = length -1 #最後乙個元素的 索引

last_par_node = length//2 -1

while last_par_node >= 0:

adjust_heap(lst, last_par_node, length-1)

last_par_node -= 1 #每調整好乙個節點,從後往前移動乙個節點

# return lst

while last > 0:

#swap(lst, 0, last)

lst[0], lst[last] = lst[last],lst[0]

# 調整堆讓 adjust 處理,最後已經排好序的數,就不處理了

adjust_heap(lst, 0, last-1)

last -= 1

return lst #將列表返回

if __name__ == '__main__':

list_ = [4, 7, 0, 9, 1, 5, 3, 3, 2, 6]

heap_sort(list_)

print(list_)

#最後結果為:

[0, 1, 2, 3, 3, 4, 5, 6, 7, 9]

堆儲存 堆排序 python實現

使用堆實現優先佇列 對於總共n個請求 使用普通陣列或者順序陣列 最差情況o n 2 使用堆 o n log n 堆的基本實現 二叉堆 任何乙個子節點都不大於他的父節點 必須是一棵完全二叉樹 用陣列儲存二叉堆 shift up shift down 基礎堆排序 heapsort1 heapify 堆排...

5排序 5堆排序

include using namespace std int n 10 元素個數 int b 11 定義全域性陣列 void shift down int i else flag 1 下乙個移動的結點是i,即沒有被更改 函式原理 對傳入的i進行下移,i移動到比它的兒子都小為止 最壞情況是移動到葉 ...

python3堆排序 python 堆排序

堆排序 堆排序 heapsort 是指利用堆這種資料結構所設計的一種排序演算法。堆積是乙個近似完全二叉樹的結構,並同時滿足堆積的性質 即子結點的鍵值或索引總是小於 或者大於 它的父節點 但是不保證所有左子樹比右子樹小反之亦然 堆排序可以說是一種利用堆的概念來排序的選擇排序。分為兩種方法 大頂堆 每個...