堆排序的原理是利用了堆这个数据结构。
heapadjust(array,start,end)方法每次可以将数组的以start为根节点的树排序好,使该树的孩子都比父亲小。
最开始的初始化阶段,start从(len(array)-2)/2开始递减,从最下面的子树开始构建堆,共heapadjust了约len(array)/2次,从而使最大值像冒泡一样从子树中冒到全树的最顶端;
之后的排序阶段,start每次都从0开始,end从len(array)-1开始每次递减,每次将最顶端的最大值拿下来,放到end处。这样,就相当于将整个序列分为了无序区和有序区。在[0,end]之间是heap的无序区,在end之后是之前排好的最大值的有序区。每次将0和end位置的值交换,从而将相当于把最大值摘下来放到最后,再通过heapadjust将之前end的值放入0位置后重新排序一下,又把剩下的heap中的最大值放到0的位置了。整体来看,无序区里面,通过heapadjust方法,每次都把最大的值放到0位置,之后将其摘下放到end的位置,这样多次之后,最后的位置是最大值,次最后的位置是次最大值……最终,0位置是最小值,从而(通过大顶堆)得到了升序排序结果。
from random import shuffle
def heapsort(arr):
for start in range((len(arr) - 2) / 2, -1, -1): #Notice: start end with -1, so that 0 could be included!
heapadjust(arr, start, len(arr) - 1)
for end in range(len(arr) - 1, 0, -1):
arr[0], arr[end] = arr[end], arr[0]
heapadjust(arr, 0, end-1)
return arr
def heapadjust(arr, root, end):
#print 'heapadjust arr:',arr,'root:',root,'end:',end
while True:
child = root * 2 + 1
if child > end: break
if child + 1 <= end and arr[child] < arr[child + 1]:
child += 1
#print 'root is',root,'child is',child
if arr[child] > arr[root]:
arr[root], arr[child] = arr[child], arr[root]
root = child
#print 'change arr to',arr
else:
break
if __name__ == '__main__':
arr = range(10)
shuffle(arr)
print 'original array is:\n',arr
result = heapsort(arr)
print 'heapsort result is:\n',result