堆排序
二叉堆是一个数组,可以被看作一个近似的完全二叉树。二叉堆可以分为两种形式:最大堆和最小堆。
在最大堆中,最大堆性质是指除了根以外的所有结点i都满足:$A[PARENT[i]]>=A[i]$
也就是说,某节点的值之多与其父结点一样大,因此,堆中的最大元素存放在根结点,并且,在任意子树中,该子树所包含的所有结点的数值都不大于该子树根结点的值。
最小堆性质是指除了根以外的所有结点i都满足:$A[PARENT[i]]<=A[i]$
堆中最小元素存放在根结点中。
堆的高度是$lg n$,n是结点数量
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859 | """维护堆的性质:输入一个数组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 Aif __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)) |