#include<stdio.h> #include<malloc.h> void Swap(int * a,int * b){ int t=*a; *a=*b; *b=t; } void AdjustHeap(int a[],int location,int n){ int key=a[location]; for(int i=2*location;i<n;i*=2){ if(i<n&&a[i]<a[i+1]) //找两者中最大的值 i++; if(key>=a[i])//确定location的位置为i break; a[location]=a[i]; location=i; } a[location]=key; } void CreateHeap(int a[],int n){ for(int i=n/2-1;i>=0;i--){ AdjustHeap(a,i,n); } } void HeapSort(int a[],int n){ for(int i=n-1;i>=0;i--){ Swap(a+i,a+0); AdjustHeap(a,0,i-1); } } void Print(int a[],int n){ for(int i=0;i<n;i++){ printf("%d ",a[i]); } printf("\n"); } int main(){ int n; while(scanf("%d",&n)!=EOF){ int * data=(int *)malloc(sizeof(int)); for(int i=0;i<n;i++){ scanf("%d",data+i); } CreateHeap(data,n); HeapSort(data,n); Print(data,n); printf("\n"); } return 0; }
堆排序:堆排序为一种选择排序。
堆的定义:n个元素的序列,当且满足以下条件时称之为堆;
1)k_s>=k_2s 且k_s>=k_2s+1 或 2)k_s<=k_2s 且k_s<=k_2s+1
前者称之为大根堆,后者称之为小根堆
堆排序的步骤:
1)创建堆、2)交换堆顶和堆尾的元素、 3)调整堆 之后将2和3步重新进行n-1次循环;
调整堆:
1)保存起始位置s的值r[s]
2) 从r[2s]和r[2s+1]选取关键字较大的
若此关键字大小小于r[s]则此堆已经完成;反之交换此关键字与r[s],并将s位置置为当前值,调整堆直至到达叶子节点为止。
初建堆:
由于叶子节点即为一个简单堆,所以对于该序列中([n/2]下取整-1)到1的节点进行调整即可。
堆排序:
交换堆顶与当前堆尾的值,并重新对堆进行调整,循环n-1次。