对于堆的概念以及它的一些基本操作,请参见我的上一篇博客。
利用堆实现排序的简单思路是,利用堆顶元素总是最大或者最小的性质,每次弹出一个元素,直到堆空,则弹出元素形成的序列是有序的。但是为了节约存储空间,我们直接将弹出的元素放在原堆内存的后面,这样形成的最后形成的有序数组的顺序是和堆中数据的顺序性是相反的(若是小根堆,排序后是由大到小的;若是大根堆,排序后是由小到大的)。代码如下所示
def heap_sort(elems):
def siftdown(elems,e,begin,end):
i,j=begin,begin*2+1
while j<end:
if j+1<end and elems[j+1]<elems[j]:
j+=1
if e<elems[j]:
break
elems[i]=elems[j]
i=j
j=2*j+1
elems[i]=e
end=len(elems)
for i in range(end//2-1,-1,-1):
siftdown(elems,elems[i],i,end) #创建堆
for i in range((end-1),0,-1):
e=elems[i]
elems[i]=elems[0]
siftdown(elems,e,0,i)
以上代码是基于小根堆的排序,其中siftdown函数也在我的上一篇博客中有讲解,是元素下沉的操作。该函数首先从传入的list创建堆。然后依次取下堆顶的元素,放在堆序列中i的位置,i是从堆序列最后位置索引到1依次减小的,每次下沉的范围下限逐渐减小。
测试代码:
elems=[2,5,6,2,5,6,7,3,2,3,6]
heap_sort(elems)
print(elems)#[7, 6, 6, 6, 5, 5, 3, 3, 2, 2, 2]