1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
"""维护堆的性质: 输入一个数组A和下标i,调用MaxHeapify时,假定根结点为左子树LEFT(i)和右子树RIGHT(i)的二叉树都是最大堆, 但此时A[i]可能会小于其孩子,这就违背了最大堆的性质。 调用MaxHeapify通过让A[i]的值在最大堆中“逐级下降”,从而使得以下标i为根结点的子树重新遵循最大堆的性质。 时间复杂度:$T(n) leq T(2n/3)+O(1),T(n)=O(lg n),h=lg n$ """ def (A, i, size): left=i<<1 right=(i<<1)+1 largest=i
if left<size and A[left]>A[i]: largest=left if right<size and A[right]>A[largest]: 大专栏 算法导论 排序算法 largest=right if largest!=i: A[i],A[largest]=A[largest],A[i] MaxHeapify(A, largest, size)
"""建堆: 自底向上的方法利用MaxHeapify,把一个大小为n=A.length的数组A[1...n]转换为最大堆。 子数组A[lfloor n/2 rfloor+1...n]中的元素都是树的叶结点。每个叶结点都看作只有一个元素的最大堆。 时间复杂度:O(n),线性时间内把无序数组构造成一个最大堆 """ def (A, size): for i in range(0,len(A)//2)[::-1]: MaxHeapify(A, i, size) return A
"""堆排序算法: 用BuildMaxHeap将输入数组A[0...n-1]构建成最大堆,其中n=A.length。 因为数组中的最大元素总在根结点A[0]中,通过它与将A[n-1]进行互换,让该元素放到正确的位置。 如果从堆中去掉结点n(A.heapsize-1),剩余结点中,原来根结点的孩子结点仍然时最大堆,而 最新的根结点可能会违背最大堆性质,为维护最大堆性质,要调用MaxHeapify(A,0,size), 从而使在A[0...n-2]上构造一个新的最大堆,直至堆的大小从n-1降到2 时间复杂度:$O(n lg n)$,BuildMaxHeap是O(n),n-1次调用MaxHeapify $ O(lg n)$ """ def HeapSort(A): size=len(A) BuildMaxHeap(A, size)
for i in range(1, len(A))[::-1]: A[0],A[i]=A[i],A[0] size-=1 MaxHeapify(A, 0, size) return A
if __name__=='__main__': import random print( "Now displaying HeapSort") s = random.randint(5, 10) A = [] for i in range(0, s): A.append(random.randint(0, 1000)) print (A) print (HeapSort(A))
|