常见排序算法-堆排序

堆排序

  堆排序将待排序列看做一棵顺序存储的二叉树,然后将其调整为大顶堆,再将堆的最后一个元素与堆顶元素进行交换。接着将前(n-1)个元素再次调节为大顶堆,将堆顶元素与当前堆的最后一个元素交换得到次大的记录,重复该过程,直到待调整堆中只有一个元素为止,即为最小记录,此时可得到一个有序序列。

(简而言之,堆排序分为两个过程:一是构建堆,二是交换堆顶元素与最后一个元素

  

def heapSort(arr):
    size=len(arr)
    for i in range(0,size//2)[::-1]:    # 经过这个for循环,arr已经大顶堆,但不一定是有序的
        adjustHeap(arr,i,size)          #只能保证堆顶的元素是最大的
    for i in range(0,size)[::-1]:
        arr[0],arr[i]=arr[i],arr[0]
        adjustHeap(arr,0,i)   ######
def adjustHeap(arr,i,size):
    lchild=2*i+1
    rchild=2*i+2
    maxs=i
    if maxs<size//2:
        if lchild<size and arr[lchild]>arr[maxs]:
       
            maxs=lchild
        if rchild<size and arr[rchild]>arr[maxs]:
       
            maxs=rchild
        if maxs!=i:
            arr[maxs],arr[i]=arr[i],arr[maxs]
            adjustHeap(arr,maxs,size)  #这个递归第一个for循环构建大顶堆是用不到的
     #因为构建的过程是从最下面的非叶节点考虑上来的,最上面一定是最大的元素,而第二个for循环交换
     #堆顶元素后,是从最上面的根节点往下考虑的,所以要用到递归,而且经过构建堆的调节,每个父节点都是
    #大于子节点的值的,所以在交换后,只需要把交换后的堆顶元素放到对应位置即可
    #简单来说,就是构建堆:本质是让非叶子节点的下沉过程,而下沉过程用到递归,然后再交换元素,交换后又是
    #堆顶元素下沉的过程
********************************************************
def heapSort(arr):
    size=len(arr)
    for i in range(0,size//2)[::-1]:    # 经过这个for循环,arr已经大顶堆,但不一定是有序的
        adjustHeap(arr,i,size)          #只能保证堆顶的元素是最大的
    for i in range(0,size)[::-1]:
        arr[0],arr[i]=arr[i],arr[0]
        for j in range(0, i // 2)[::-1]:
            adjustHeap(arr,j,i)   

def adjustHeap(arr,i,size):
    lchild=2*i+1
    rchild=2*i+2
    maxs=i
    if maxs<size//2:
        if lchild<size and arr[lchild]>arr[maxs]:
            maxs=lchild
        if rchild<size and arr[rchild]>arr[maxs]:
            maxs=rchild
        if maxs!=i:
            arr[maxs],arr[i]=arr[i],arr[maxs]
            #这是由最下面的非叶子节点向上来考虑的,所以能保证堆顶是是最大的元素
            #不用递归了。

  

原文地址:https://www.cnblogs.com/wanrongshu/p/12719173.html