堆排序是面试中比较常考的排序方法,所以在找工作时我们自己必须能手撕出来堆排序。
堆排序的思想为:我们在堆排序的时候需要将数组想象成一颗完全二叉树。那么就满足:每一个父节点所对应的子节点的左子树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)