#在建立堆和排序堆的过程都需要反复的进行调整成最小或最大堆 def heap_sort(elems,e,begin,end): def siftdown(elems,e,begin,end):#e是要调整的子堆中的堆顶元素,begin是其在列表中的位置 i,j = begin,begin*2+1 #这样的话i是堆顶元素,j是其左子树 while j < end: #需要将最小元素放在elems[i]中 if j+1 < end and elems[j+1] < elems[j]: j+=1 #如果右子树大于左子树,j 中存的是子树中较小的下标。 if e < elems[j]: #e是当前三个元素中最小的元素 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): #建堆的时候叶子节点就一个值,已经是一个堆了,所以从第一个非叶子节点进行调整,这里这样表示向下取整 siftdown(elems,elems[i],i,end) #所谓的调整就是将一个根节点和两个堆进行位置的调整 #print(elems) for i in range((end-1),0,-1): #建好堆以后开始排序,排序的时候是从数组的最后一个元素开始 e = elems[i] #将堆中的最后一个元素赋值给e elems[i] = elems[0] #将堆顶的元素赋值给最后一个元素,因为这里并没有每次从堆顶弹出来的最小元素开辟一个新的存储空间 #而是借用以前的存储空间,插入最后一个元素的位置,所以这样出来的数组的顺序可能是从小到大的 siftdown(elems,e,0,i) #接下来继续调整堆为小顶堆,从上往下进行调整 #print("每一次:") #print(elems) return elems print("最终的排序结果为:") print(heap_sort([2,6,9,0,1,5,7,2],2,0,8)) print(heap_sort([2,5,9,0,3,5,7,8,18],2,0,9)) #最终的排序结果为: #[9, 7, 6, 5, 2, 2, 1, 0] #[18, 9, 8, 7, 5, 5, 3, 2, 0]