#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次。