堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。
堆的定义
n个元素的序列{k1,k2,…,kn}当且仅当满足下列关系之一时,称之为堆。
情形1:ki <= k2i 且ki <= k2i+1 (最小化堆或小顶堆)
情形2:ki >= k2i 且ki >= k2i+1 (最大化堆或大顶堆)
堆的存储
一般用数组来表示堆,若根结点存在序号0处, i结点的父结点下标就为(i-1)/2。i结点的左右子结点下标分别为2*i+1和2*i+2。
(注:如果根结点是从1开始,则左右孩子结点分别是 2i 和 2i+1。);如第0个结点左右子结点下标分别为1和2。
- 堆排序思想:
堆排序就是利用堆(小顶堆或大顶堆)进行排序的方法。比如利用大顶堆:
1.将待排序的序列构造成一个大顶堆。此时,整个序列的最大元素就是堆顶的跟结点
2.跟堆尾的元素互换,此时堆尾的元素最大,
3.将剩下的元素再构建一个大顶堆,重复2步骤。 - 堆排序的时间复杂度:平均时间复杂度为O(N*logN)。最好最差也为O(N*logN)。;
- 堆排序是一种不稳定的排序算法,需要一个辅助空间
下面举例子说明:
算法实现:
#include<stdio.h>
void heapJust(int arr[],int start,int end){
int j;
arr[0]=arr[start];//arr[0]为哨兵
for(j=2*start;j<=end;j*=2){
if(j<end&&arr[j]<arr[j+1]){
++j;
}
if(arr[0]>=arr[j]){
break;
}
arr[start]=arr[j];
start=j;
}
arr[start]=arr[0];
}
void heapSort(int arr[],int size){
int i;
for(i=size/2;i>0;i--){//先建成大顶堆
heapJust(arr,i,size);
}
for(i=size;i>1;i--){
arr[0]=arr[i];//将堆顶记录和未经排序的子序列的最后一个记录交换
arr[i]=arr[1];
arr[1]=arr[0];
heapJust(arr,1,i-1);//将剩余的i-1个元素重新调整为大顶堆
}
}
int main(){
int n;
scanf("%d",&n);
int arr[n],i;
for(i=1;i<=n;i++){
scanf("%d",&arr[i]);
}
heapSort(arr,n);
for(i=1;i<=n;i++){
printf("%d ",arr[i]);
}
return 0;
}