堆排序算法主要过程是保持堆的性质:max_heapify()。它的作用是:
对一个大顶堆,如果拿掉堆顶元素,换成另一个元素,如果这个元素比堆顶的左右儿子小,那么就不满足大顶堆的性质,这时,max_heapify()通过逐步向下进行更新,可以达到维护大顶堆的效果,具体是将新的堆顶元素与左右儿子比较,如果比左右儿子都大说明不用更新就是一个大顶堆了;如果比左儿子小,将这个值与左儿子互换,然后对左子树递归进行同样的操作,最后形成一个大顶堆。
堆排序的过程是,首先对所给元素建一个大顶堆,那么这些元素中的最大值显然就是堆顶元素了,然后,把这个元素放到序列(数组)的最后,对除了它之外的元素进行一次max_heapify,找出剩余元素中的最大值,放到倒数第二位置,以此类推,最后得到升序序列。
View Code
# include <stdio.h> # define lson(i) ( (i) << 1 ) # define rson(i) ( ((i) << 1) + 1) /*******************************************************************/ void swap(int * x, int * y) { int tmp; tmp = *x; *x = *y; *y = tmp; } void max_heapify(int * A, int i, int heapsize) { int l, r, largest; l = lson(i); r = rson(i); if ( l<=heapsize && A[l]>A[i] ) { largest = l; } else { largest = i; } if ( r<=heapsize && A[r]>A[largest] ) { largest = r; } if ( largest != i ) { swap(&A[i], &A[largest]); max_heapify(A, largest, heapsize); } } void build_max_heap(int * A, int n) { int i; for (i = n/2; i >= 1; --i) { max_heapify(A, i, n); } } void heap_sort(int * A, int n) { int heapsize, i; heapsize = n; build_max_heap(A, n); for (i = n; i >= 2; --i) { swap(&A[i], &A[1]); --heapsize; max_heapify(A, 1, heapsize); } } /*******************************************************************/ void init(int * A, int n) { int i; A[0] = n; for (i = 1; i <= n; ++i) { scanf("%d", &A[i]); } } void solve(int * A, int n) { heap_sort(A, n); } /*******************************************************************/ int main() { int A[100005]; int n, i; freopen("heap_sort.txt", "r", stdin); while (~scanf("%d", &n)) { init(A, n); solve(A, n); for (i = 1; i <= n; ++i) { printf("%d", A[i]); printf(i<n ? " ":"\n"); } } return 0; }