heapsort
2012-12-05 17:28
363 查看
/* * szlHeapSort.h */ #ifndef SZL_HEAP_SORT_H #define SZL_HEAP_SORT_H void heapSort(int a[], int n); void siftDown(int a[], int root, int n); #endif
/* * szlSwap.h */ #ifndef SZL_SWAP_H #define SZL_SWAP_H //交换两个数 void swap(int *a, int *b); #endif
/* szlHeapSort.c * 堆是其节点值满足一定约束的完全二叉树; * 数组实现的n个节点的完全二叉树满足的性质,如果 * 1.用A[0..n-1]表示这棵树,那么 * (1)位置i的父节点为(i-1)/2; * (2)位置i的孩子节点为2*i+1及2*i+2; * (3)第一个叶子节点是n/2; * 2.用A[1..n]表示这棵树,那么 * (1)位置i的父节点为i/2; * (2)位置i的孩子节点为2*i及2*i+1; * (3)第一个叶子节点是n/2+1; */ #include "szlHeapSort.h" #include "szlSwap.h" #include "stdio.h" /* * 将具有n个元素的数组a进行堆排序 */ void heapSort(int a[], int n){ int i; /* * 以数组a为输入,建立一个堆 */ for(i=(n/2)-1; i>=0; i--){ // 从最后一个内部节点降序地访问到树根节点 siftDown(a,i,n); // 将每一个节点下沉,建立以位置i为根节点的子堆,sub heap } /* * 将树根节点和最后一个叶子节点交换; * 并将堆的大小减少1; * 然后调整树根,以保持堆序; * 循环,直至访问到第2个元素 */ for(i=n-1; i>=1; i--){ swap(&a[0],&a[i]); siftDown(a,0,i); } } /* * 将root位置的节点在大小为n的堆a中调整,以保持堆序 */ void siftDown(int a[], int root, int n){ int done, maxChild; done = 0; while(!done){ if(root*2+2<=n-1){ //如果root存在左孩子和右孩子 if(a[root*2+1]>a[root*2+2]){ //max记住较大的孩子 maxChild=root*2+1; } else{ maxChild=root*2+2; } } else if(root*2+1==n-1){ // 如果root有左孩子 maxChild=root*2+1; } else{ //没有孩子节点 maxChild = root; // 标记root为最大的元素 } if(a[root] < a[maxChild] ){ // 将最大的元素和root位置的元素交换 swap(&a[maxChild],&a[root]); root=maxChild; //以较大的孩子为根节点继续往下访问 } else{ done=1; } } }
/* * szlSwap.c */ #include "szlSwap.h" void swap(int *a, int *b){ int t=*a; *a=*b; *b=t; }
更为简洁的版本:
/* * heapsort.c */ #include <stdio.h> #define N 30 void swap (int * p, int * q){ if (! (p == q)){ * p ^= * q; * q ^= * p; * p ^= * q; } } void sift_down (int a[], int i, int n){ int max = i; if ( 2*i+2 <= n-1){ max = a[2*i+1] > a[2*i+2] ? (2*i+1) : (2*i+2); } else if (2*i+1 == n-1){ max = 2*i+1; } if (a[max] > a[i]){ swap (&a[i], &a[max]); sift_down (a, max, n); /* recursion */ } } void build_heap (int a[], int n){ int i; for (i=(n-1)/2; i>=0; i--){ sift_down (a, i, n); } } void heapsort (int a[], int n){ int i; build_heap (a, n); for (i=n-1; i>0; i--){ swap (&a[0], &a[i]); sift_down (a, 0, i); } } int main (int argc, char ** argv){ int n; int i; int a ; #ifdef DEBUG1 freopen ("in.txt", "r", stdin); #endif scanf ("%d", &n); for (i=0; i<n; i++) scanf ("%d", &a[i]); heapsort (a, n); for (i=0; i<n; i++) printf ("%d ", a[i]); #ifdef DEBUG1 fclose (stdin); #endif return 0; }