代碼
#coding:utf-8 #author:徐卜靈 # 堆排序適用於記錄數很多的情況 #與快速排序,歸並排序 時間復雜一樣都是n*log(n) #################################################### #################################################### #################################################### # from collections import deque # # # 這里需要說明元素的存儲必須要從1開始 # # 涉及到左右節點的定位,和堆排序開始調整節點的定位 # # 在下標0處插入0,它不參與排序 # L = deque([49,38,65,97,76,13,27,49]) # L.appendleft(0) # # #L = [0,49,38,65,97,76,13,27,49] # # def element_exchange(numbers,low,high): # # temp = numbers[low] # # # j 是low的左孩子節點(cheer!) # i = low # j = 2*i # # while j<=high: # # 如果右節點較大,則把j指向右節點 # if j<high and numbers[j]<numbers[j+1]: # j = j+1 # if temp<numbers[j]: # # 將numbers[j]調整到雙親節點的位置上 # numbers[i] = numbers[j] # i = j # j = 2*i # else: # break # # 被調整節點放入最終位置 # numbers[i] = temp # # def top_heap_sort(numbers): # # length = len(numbers)-1 # # # 指定第一個進行調整的元素的下標 # # 它即該無序序列完全二叉樹的第一個非葉子節點 # # 它之前的元素均要進行調整 # # cheer up! # first_exchange_element = length/2 # # #建立初始堆 # print first_exchange_element # for x in range(first_exchange_element): # element_exchange(numbers,first_exchange_element-x,length) # # # 將根節點放到最終位置,剩余無序序列繼續堆排序 # # length-1 次循環完成堆排序 # for y in range(length-1): # temp = numbers[1] # numbers[1] = numbers[length-y] # numbers[length-y] = temp # element_exchange(numbers,1,length-y-1) # # if __name__=='__main__': # top_heap_sort(L) # LL = [] # for x in range(1,len(L)): # # print L[x], # LL.append(L[x]) # print LL ############################################## ############################################## ############################################## def build_maxheap(L,len): for i in range(len/2,0,-1): # print i adjustdown(L,i,len) return L def adjustdown(L,low,high): #這里只是把一個位於low位置上的數向下移動。 temp = L[low] i = low j = 2 * i while j <= high: # if j <= high and L[j] < L[j+1]:#z這里的L[j+1]可能不存在,所有會有out of index 報錯. # j+=1 if j <= high and j + 1 <= high: if L[j] < L[j+1]: j+=1 if L[j]>temp: L[i] = L[j] i = j j = 2 * i else: break L[i] = temp # return L #由於這里是中間列表,不要輸出。 # print L # L = [0,49,38,65,97,76,13,67,47] # L = build_maxheap(L,8) # del L[0] # # print type(L) # print "大根堆第一次:",L len = len(L)-1 def Heap_sort(L,len): build_maxheap(L,len) for i in range(len,1,-1): L[i],L[1] = L[1],L[i] # print i # print L[len],L[1] adjustdown(L,1,i-1) return L L = [49,38,65,97,76,13,67,47] print "原列表:" ,L L.insert(0,0) L = Heap_sort(L,len) del L[0] print "堆排序:",L #基本思路是: # 1先從后到前進行小數下移的操作。這個后是指len(L)/2 #2.第一步完成后,最大的那個數就上移到了根節點。把這個根節點與最后一個元素交換位置,這時最后一個元素就在有序區里。則只需要將第一個元素再進行下移操作即可。 #3.循環第二步,直到只剩下根節點。
堆排序真的是排序算法中我花費時間最多的算法了,最開始是理解原理上出了問題。理解了之后寫代碼又出了問題。
對於二叉樹不是很熟的最好復習一下樹的知識。
理解了之后就能很好的寫代碼了。
思路:
1.從len(L)/2 到1開始,建立大根堆。這里需要注意的是:這里的元素並不是一次就能移動到最終的位置的。只有迭代到第一個元素,才能建立一個大根堆。
2.將堆頂元素與無序區最后一個元素交換位置,破壞了大根堆,則重新建立大根堆。
3.迭代第二步,直到只剩下一個元素。
時間復雜度:O(nlogn)
空間復雜讀:O(nlogn)
跟快排是一樣的。
堆排序也是不穩定的排序方法,這一定要搞清楚。