堆排序基本思想:首先建立一个大根堆。将第一大的值输出来,用最后一个值去替换第一大值的位置,然后进行筛选,重新得到一个堆,得到n个元素的次大值。如此反复执行,得到一个有序序列,这个过程称为堆排序。
建堆:对于一个n个元素的序列,从下标为floor(n/2)这个元素开始,直到1,对每个元素进行筛选,筛选完后,即可保证以该元素为根的子树是一个堆。
时间复杂度:堆排序在最坏情况下的时间复杂度也为O(nlogn)
空间复杂度:O(n)。
//堆排序
#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
const int maxn = 1e3+200;
struct Heap{
int key;
}heap[maxn];
void HeapAdjust(int s,int m){ //堆调整
Heap rt = heap[s]; //记录开始的节点
for(int i = s*2; i <= m; i *= 2){
if(i < m && heap[i].key < heap[i+1].key) i++; //比较左右子节点大小
if(heap[i].key < rt.key) break; //如果最大的子节点没有rt的值大,结束
heap[s] = heap[i];
s = i;
}
heap[s] = rt;
}
int main(){
int n;
while(scanf("%d",&n)!=EOF){
for(int i = 1; i <= n; i++){
scanf("%d",&heap[i].key);
}
for(int i = n/2; i >= 1; i--){ //最后一个非终端节点floor(n/2)
HeapAdjust(i,n);
}
for(int i = 1; i <= n; i++){
printf("%d %d
",i,heap[i].key);
}puts("");
for(int i = n; i >= 2; i--){
printf("%d ",heap[1].key);
swap(heap[1],heap[i]);
HeapAdjust(1,i-1);
}printf("%d
",heap[1]);
for(int i = 1; i <= n; i++){
printf("%d %d
",i,heap[i].key);
}puts("");
}
return 0;
}