几种常用的排序方法5--堆排序
堆排序
堆排序是一种原地排序,利用数据结构中的堆来管理数据。
(二叉)堆数据结构是一组数组对象,它可以被视为一个完全二叉树,树的每个节点与数组中存放该结点值得那个元素对用。
性质:
①父节点:i 左孩子::2*i 右孩子:2*i + 1 (注意:在计算机中可以用移位完成,左孩子是i<<1,右孩子是(i<<1) + 1)
②二叉堆有两种:最大堆和最小堆,这里以最大堆为例:除了根以外的每个结点i,有A[parent[i]] >= A[i],即每个结点的值最多与其父结点一样大。
③当用数组表示存储了n个元素的堆时,叶子结点的下标是[n/2]+1, [n/2]+2,......n。
堆排序算法的主要思想:
①首先初始化一个最大堆,此最大堆是一个无序区R[1,2,...n];
②根据最大堆的性质,根结点的元素R[1]一定是最大的元素,将R[1]与R[n]交换,得到新的有序区R[n]和无序区R[1,2,3...n-1];
③将无序区的元素重新再次调整为最大堆,重复②的做法,直到无序区只有一个元素。
堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Max_Heapify实现的。
堆排序比较适合数据较多的文件排序
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define MAXN 10000 4 void Max_Heapify(int *A, int i, int n) 5 { 6 int largest; //临时变量,存放数大的那个结点 7 int l = i << 1; //左孩子 8 int r = (i << 1) + 1; //右孩子 9 if(l <= n && A[l] > A[i]) //把大的数给largest 10 { 11 largest = l; 12 } 13 else largest = i; 14 if(r <= n && A[r] > A[largest]) 15 { 16 largest = r; 17 } 18 if(largest != i) 19 { 20 int temp = A[i]; //交换A[i]和较大的孩子 21 A[i] = A[largest]; 22 A[largest] = temp; 23 Max_Heapify(A,largest,n); //递归调用 24 } 25 } 26 27 void Build_Max_Heap(int *A, int n) 28 {//建立堆 29 //子数组A[n/2,(n/2+1)....n]中的元素都是树中的叶子,看作只含一个元素的堆。 30 //对树中的每一个其它的结点调用一个Max_Heapify() 31 for(int i = n/2 ; i >= 1; i--) 32 { 33 Max_Heapify(A,i,n); 34 } 35 } 36 37 void HeapSort(int *A, int n) //堆排序 38 { 39 Build_Max_Heap(A,n); 40 for(int i = n; i >= 1 ;i-- ) 41 { 42 int t = A[i]; //交换A[0] 和A[i]的值,即将树根(最大的数)放入数组末 43 A[i] = A[1]; 44 A[1] = t; 45 Max_Heapify(A,1,i - 1); //从新调整最大堆 46 } 47 } 48 49 int main() 50 { 51 int a[MAXN]; 52 int n; 53 while(scanf("%d",&n) == 1 && n > 0) 54 { 55 int i; 56 for(i = 1; i <= n; i++) 57 { 58 scanf("%d",&a[i]); 59 } 60 HeapSort(a,n); 61 for(i = 1; i <= n; i++) 62 { 63 printf("%d ",a[i]); 64 } 65 } 66 printf("\n"); 67 // system("pause"); 68 return 0; 69 }