算法思想(以大顶堆为例):
1.将长度为n的待排序的数组进行堆有序化构造成一个大顶堆
2.将根节点与尾节点交换并输出此时的尾节点
3.将剩余的n -1个节点重新进行堆有序化
4.重复步骤2,步骤3直至构造成一个有序序列
#include<stdio.h>
void Swap(int* arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
//构造大根堆(通过新插入的数上升)
void HeapInsert(int* arr,int length){
int i;
for(i=0;i<length;i++){
int currentIndex=i; //当前插入的索引
int fatherIndex=(currentIndex-1)/2; //父结点索引
//如果当前插入的值大于其父结点的值,则交换值,并且将索引指向父结点
//然后继续和上面的父结点值比较,直到不大于父结点,则退出循环
while(arr[currentIndex]>arr[fatherIndex]){
Swap(arr,currentIndex,fatherIndex);//交换当前结点与父结点的值)
currentIndex=fatherIndex; //将当前索引指向父索引
fatherIndex=(currentIndex-1)/2;//重新计算当前索引的父索引
}
}
}
//将剩余的数构造成大根堆(通过顶端的数下降)
void Heapify(int* arr,int index,int size){
int left=index*2+1;
int right=index*2+2;
while(left<size){
int largestIndex;
//判断孩子中较大的值的索引(要确保右孩子在size范围之内)
if(arr[left]<arr[right]&&right<size){
largestIndex=right;
}else{
largestIndex=left;
}
//比较父结点的值与孩子中较大的值,并确定最大值的索引
if(arr[index]>arr[largestIndex]){
largestIndex=index;
}
//如果父结点索引是最大值的索引,那已经是大根堆了,则退出循环
if(index==largestIndex){
break;
}
//父结点不是最大值,与孩子中较大的值交换
Swap(arr,largestIndex,index);
//将索引指向孩子中较大的值的索引
index=largestIndex;
//重新计算交换之后的孩子的索引
left=index*2+1;
right=index*2+2;
}
}
//堆排序
void HeapSort(int* arr,int length){
HeapInsert(arr,length);//构造大根堆
while(length>0){
Swap(arr,0,length-1); //固定最大值
length--;
Heapify(arr,0,length); //构造大根堆
}
}
void PrintArr(int* arr, int length){
int i;
for ( i = 0; i < length; i++){
printf("%d ", arr[i]);
}
printf("\n");
}
int main(){
int a[10]={5,1,9,3,7,4,8,6,2,0};
int length = sizeof(a)/sizeof(a[0]);
HeapSort(a,length);
PrintArr(a,length);
return 0;
}
时间复杂度:O(nlogn)
空间复杂度:O(1)
图解流程:https://blog.csdn.net/u010452388/article/details/81283998