堆排序
算法思想:
1.堆排序应用了最小(大)堆的根节点是最小(大)值这一特性。
2.每次取出根结点的最值,再将最右边的叶结点放到根结点的位置。
3.基于第二步,向下调整根结点的元素,直到变成一个新的最小(大)堆。
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int data[1001];
int length;
}Heap;//堆的数据类型
void Swap(int *a,int *b);//交换
Heap *Init_heap(int length);//将heap数组初始化成堆
void Down(Heap *h,int i);//将第i号结点向下调整
void Heapsort(Heap *h,int data[]);//堆排序
int main(void){
int n;
int data[1001];
printf("请输入元素个数:");
scanf("%d",&n);
Heap *h=Init_heap(n);
Heapsort(h,data);
for(int i=0;i<n;++i)
printf("%3d",data[i]);
return 0;
}
void Swap(int *a,int *b){
int t;
t=*a;
*a=*b;
*b=t;
return ;
}
Heap *Init_heap(int length){
Heap *h=(Heap *)malloc(sizeof(Heap));
h->length=length;
printf("请输入%d个数:",length);
for(int i=1;i<h->length+1;++i)
scanf("%d",h->data+i);
/****生成最小堆*****/
//从后向前遍历,找父节点,若比父节点小,则交换
for(int i=length;i>1;--i){
if(h->data[i]<h->data[i/2])
Swap(h->data+i,h->data+i/2);
}
return h;
}
void Down(Heap *h,int i){
int flag;//flag用来记录是否发生了交换
while(i*2<h->length+1){//存在左子结点
//将flag置为1
flag=1;
if(i*2+1<h->length+1){//存在右子结点
if(h->data[i]>h->data[i*2+1] && h->data[i*2]<h->data[i*2+1]){
Swap(h->data+i,h->data+i*2);
i*=2;
flag=0;
}
else if(h->data[i]>h->data[i*2] && h->data[i*2+1]<h->data[i*2]){
Swap(h->data+i,h->data+i*2+1);
i=i*2+1;
flag=0;
}
}
else if(h->data[i*2]<h->data[i]){
Swap(h->data+i*2,h->data+i);
i*=2;
flag=0;
}
if(flag)//没有发生交换,说明调整完成
break;
}
return ;
}
void Heapsort(Heap *h,int data[]){
int i=0;
while(h->length){//当堆的结点个数变成0,则排序完成
//将根结点弹出
data[i++]=h->data[1];
//将最右边的叶结点放到根结点的位置
h->data[1]=h->data[h->length--];
//向下调整
Down(h,1);
}
return ;
}