算法學習:堆排序
一、關于二叉樹和堆的基本概念
1、二叉樹
每個節(jié)點,最多有2個子樹的數(shù)結構。
左右子樹,也是最多有2個子節(jié)點。
2、滿二叉樹
除最后一層外,每個節(jié)點都有2個子節(jié)點。
3、完全二叉樹
存在的節(jié)點,和滿二叉樹的節(jié)點完全對應。
4、堆:
Max Heap:最大的元素永遠在根節(jié)點
任一非終端節(jié)點數(shù)據(jù)均不小于其左、右孩子節(jié)點。
Min Heap: 最小的元素永遠在根節(jié)點
任一非終端節(jié)點數(shù)據(jù)均不大于其左、右孩子節(jié)點。
5、堆的特點:
i 表示索引,用公式找到索引所在節(jié)點的父節(jié)點和左右孩子節(jié)點的索引。
parent = (i-1)//2
c1 = 2*i+1
c2 = 2*i+2
二、堆排序的核心思想
以Max Heap 為例:
第一步:建堆,保證最大元素是堆頂
第二步:把堆頂元素和最后一個元素位置交換
第三步:調整堆結構,使堆滿足 Max Heap ,調整的時候不再考慮最后一個位置元素
第四步:再次將堆頂元素和調整后堆的最后一個元素位置交換
第五步:調整堆結構
第六步:循環(huán)
考慮實現(xiàn)過程:
1.如何讓數(shù)組滿足堆的定義:建堆
構建堆的過程:
1)從堆的最后一個非葉子節(jié)點開始,進行調整
對于長度為n的堆,確定最后一個非葉子節(jié)點的位置:n//2-1
調整過程:在最后一個非葉子節(jié)點 的左右子節(jié)點中,找到最大的元素,交換位置
2)找到倒數(shù)第二個非葉子節(jié)點,不滿足Max需要調整,滿足則不調整
3)一直找到最后一個非葉子節(jié)點進行調整,最后滿足了Max Heap的條件
堆頂元素和最后一個元素,交換。
交換后破壞了原有堆的結構。
然后縮小堆的規(guī)模,繼續(xù)調整成Max Heap。
2. 調整完以后,繼續(xù)交換
三、代碼
#調整堆結果 def heapify(arr,action_node_index,length): ''' arr:要傳入的數(shù)組 action_node_index:待調整的堆的節(jié)點的索引 length :堆的規(guī)模 ''' left_child_index = 2*action_node_index+1 right_child_index = 2*action_node_index+2 max_value_index = action_node_index #分別和左右子節(jié)點比較,找到最大的值對應的index #在查找的堆的范圍內 if left_child_index<length and arr[left_child_index]>arr[max_value_index]: max_value_index = left_child_index if right_child_index<length and arr[right_child_index]>arr[max_value_index]: max_value_index = right_child_index #如果最大值的索引發(fā)生了變化,交換位置 if max_value_index!=action_node_index: arr[max_value_index],arr[action_node_index]=arr[action_node_index],arr[max_value_index] #因為位置的交換,可能導致交換后的堆不滿足堆的結構 #繼續(xù)調整基于該節(jié)點為根的堆結構 heapify(arr,max_value_index,length) #建堆:從最后一個非葉子節(jié)點 def buildheapify(arr): for i in range(len(arr)//2-1,-1,-1):#左必右開,到0索引結束 heapify(arr,i,len(arr)) #堆排序 def heapifySort(arr): length = len(arr) buildheapify(arr) for i in range(length): #做交換 arr[0],arr[length-i-1]=arr[length-i-1],arr[0] #調整堆 heapify(arr,0,length-1-i) return arr arr = [-111,12,0,-6,12,88,34,8,-3] print(heapifySort(arr)) #結果 [-111, -6, -3, 0, 8, 12, 12, 34, 88]
2、時間復雜度:O(nlogn)
浙公網安備 33010602011771號