Python入門篇-數據結構堆排序Heap Sort
python
做者:尹正傑算法
版權聲明:原創做品,謝絕轉載!不然將追究法律責任。數據結構
一.堆Heap編碼
堆是一個徹底二叉樹
每一個非葉子結點都要大於或者等於其左右孩子結點的值稱爲大頂堆
每一個非葉子結點都要小於或者等於其左右孩子結點的值稱爲小頂堆
根結點必定是大頂堆中的最大值,必定是小頂堆中的最小值
二.大頂堆spa
徹底二叉樹的每一個非葉子結點都要大於或者等於其左右孩子結點的值稱爲大頂堆
根結點必定是大頂堆中的最大值
三.小頂堆code
徹底二叉樹的每一個非葉子結點都要小於或者等於其左右孩子結點的值稱爲小頂堆
根結點必定是小頂堆中的最小值
四.構建徹底二叉樹orm
待排序數字爲30,20,80,40,50,10,60,70,90. 構建一個徹底二叉樹存放數據,並根據性質5對元素編號,放入順序的數據結構中. 構造一個列表爲[0,30,20,80,40,50,10,60,70,90].
五.構建大頂堆 blog
1>.核心算法排序
度數爲2的結點A,若是它的左右孩子結點的最大值比它大的,將這個最大值和該結點交換.
度數爲1的結點A,若是它的左孩子的值大於它,則交換.
若是結點A被交換到新的位置,還須要和其孩子結點重複上面的過程.
2>.起點結點的選擇utf-8
從徹底二叉樹的最後一個結點的雙親結點開始,即最後一層的最右邊葉子結點的父結點開始. 結點數爲n,則起始結點的編號爲n//2(性質5).
3>.下一個結點的選擇
從起始結點開始向左找其同層結點,到頭後再從上一層的最右邊結點開始繼續向左逐個查找,直至根結點.
4>.大頂堆的目標
確保每一個結點的都比左右結點的值大.
5>.排序
將大頂堆根結點這個最大值和最後一個葉子結點交換,那麼最後一個葉子結點就是最大值,將這個葉子結點排除在待排序結點以外.
從根結點開始(新的根結點),從新調整爲大頂堆後,重複上一步.
堆頂和最後一個結點交換,並排除最後一個結點.
6>.代碼實現
1 #!/usr/bin/env python 2 #_*_coding:utf-8_*_ 3 #@author :yinzhengjie 4 #blog:http://www.cnblogs.com/yinzhengjie/tag/python%E8%87%AA%E5%8A%A8%E5%8C%96%E8%BF%90%E7%BB%B4%E4%B9%8B%E8%B7%AF/ 5 #EMAIL:y1053419035@qq.com 6 7 8 import math 9 10 11 def print_tree(array): 12 index = 1 13 depth = math.ceil(math.log2(len(array))) #由於補0了,否則應該是math.ceil(math.log2(len(array) + 1) 14 sep = " " 15 for i in range(depth): 16 offset = 2 ** i 17 print(sep * (2 **(depth - i -1)-1),end="") 18 line = array[index:index + offset] 19 for j,x in enumerate(line): 20 print("{:>{}}".format(x,len(sep)),end="") 21 interval = 0 if i == 0 else 2 ** (depth - i) -1 22 if j < len(line) - 1: 23 print(sep * interval,end="") 24 index += offset 25 print() 26 27 #爲了和編碼對應,增長一個無用的0在首位 28 origin = [0,30,20,80,40,50,10,60,70,90] 29 total = len(origin) - 1 #初始化排序元素個數,即n 30 print(origin) 31 32 print_tree(origin) 33 print_tree("=" * 50) 34 35 36 37 def heap_adjust(n,i,array:list): 38 """ 39 調整當前結點(核心算法) 40 調整的節點的起點在n//2,保證全部的調整的結點都有孩子結點 41 :param n: 待比較數個數 42 :param i: 當前結點的下標 43 :param array:待排序的數據 44 :return: 45 """ 46 while 2 * i <= n: 47 #孩子結點判斷2i位左孩子,2i+1爲右孩子 48 lchile_index = 2 * i 49 max_child_index = lchile_index #n = 2i 50 if n > lchile_index and array[lchile_index +1] > array[lchile_index]: #n > 2i說明還有右孩子 51 max_child_index = lchile_index + 1 #n = 2i +1 52 53 #和子樹的根結點比較 54 if array[max_child_index] > array[i]: 55 array[i],array[max_child_index] = array[max_child_index],array[i] 56 i = max_child_index #被比較後,須要判斷是否須要調整 57 else: 58 break 59 60 #構建大頂推,大根堆 61 def max_heap(total,array:list): 62 for i in range(total//2,0,-1): 63 heap_adjust(total,i,array) 64 return array 65 66 print_tree(max_heap(total,origin)) 67 print_tree("=" * 50) 68 69 #排序 70 def sort(total,array:list): 71 while total > 1: 72 array[1],array[total] = array[total],array[1] #堆頂和最後一個結點交換 73 total -= 1 74 if total == 2 and array[total] >= array[total -1]: 75 break 76 heap_adjust(total,1,array) 77 return array 78 79 print_tree(sort(total,origin)) 80 print_tree(origin) 81
六.總結
是利用堆性質的一種選擇排序,在堆頂選出最大值或者最小值
時間複雜度.
堆排序的時間複雜度爲O(nlogn).
因爲堆排序對原始記錄的排序狀態並不敏感,所以它不管是最好、最壞和平均時間複雜度均爲O(nlogn).
1>.空間複雜度
只是使用了一個交換用的空間,空間複雜度就是O(1).
2>.穩定性
不穩定的排序算法.