堆排序是面試中比較常考的排序方法,所以在找工作時我們自己必須能手撕出來堆排序。
堆排序的思想爲:我們在堆排序的時候需要將數組想象成一顆完全二叉樹。那麼就滿足:每一個父節點所對應的子節點的左子樹2*n+1,右子樹爲2*n+2。將此樹變成大頂堆,然後每次取堆頂元素和堆尾的最後一個元素進行交換,然後繼續將len(list)-1進行變成大頂堆。以此類推直到遍歷所有數組。
大頂堆:任何一個樹的子樹最大值就是他的頭
小頂堆:任何一個樹的子樹最小值就是他的頭
左子樹:2*n+1
右子樹:2*n+2
代碼實現:
#完全二叉樹
#大根堆 任何一個樹的子樹最大值就是他的頭
#小根堆 任何一個樹的子樹最小值是他的頭b
#左孩子 2*i+1
#右孩子 2*i+2
class HeapSort():
def heapSort(self,list):
if list is None or len(list)<2:
return
for i in range(len(list)):
#建立大根堆
self.heapInsert(list,i) #0-i
size = len(list)-1
list[0],list[size] = list[size],list[0]
while size>0:
self.heapify(list,0,size)
size -= 1
#再次進行最大元素與堆尾元素進行交換
list[0],list[size] = list[size],list[0]
def heapInsert(self,list,index):
#如果後面的元素的值大於父節點就交換
#可以循環到最頂端
while list[index] > list[(index-1)//2]:
list[index],list[(index-1)//2] = list[(index-1)//2],list[index]
index = (index-1)//2
#交換後讓堆變成大頂堆
def heapify(self,list,index,size):
left = index*2+1
while left < size:
#先對兩個子樹進行比較
if left+1 < size and list[left+1] > list[left]:
largest = left+1
else:
largest = left
largest = largest if list[largest] > list[index] else index
if largest == index:
break
list[largest],list[index] = list[index],list[largest]
index = largest
left = index*2+1
if __name__ == '__main__':
list = [5,6,2,1,8,2,0,3,8]
hs = HeapSort()
hs.heapSort(list)
print(list)