#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
void max_heapkeep(int a[], int heapsize, int i){//将a树的第i个元素“下沉”,使其保持最大堆的性质,heapsize为堆的大小
int l = 2*i;//左孩子
int r = 2*i + 1;//右孩子
int largest;//用于标记左孩子、右孩子和父亲节点中最大的那个元素的下标
if(l <= heapsize && a[l] > a[i]){
largest = l;
}
else largest = i;
if(r <= heapsize && a[r] > a[largest]){
largest = r;
}
if(largest != i){
int temp;
temp = a[i];
a[i] = a[largest];
a[largest] = temp;//如果发现有孩子节点比父亲节点小后,将父亲节点与最大的那个孩子节点交换
max_heapkeep(a, heapsize, largest);//递归调用保持最大堆这一函数,直到叶子节点或两个孩子节点都比父亲节点小
}
}
void build_max_heap(int a[],int asize){//建最大堆,原理就是从底向上调用max_heapkeep
for(int i = asize/2; i >= 1; i--){
max_heapkeep(a,asize, i);
}
}
void heapsort(int a[], int asize){//堆排序时间复杂度为n*lgn
build_max_heap(a, asize);
for(int i = asize; i >= 2; i--){
int temp;
temp = a[i];
a[i] = a[1];
a[1] = temp;
asize = asize - 1;
max_heapkeep(a, asize, 1);
}
}
int main(){
int a[] = {0, 16, 4, 10, 14, 7, 9, 3,2, 8,1};//注意以上函数中涉及的数组下标从1开始
max_heapkeep(a, 10, 2);
for(int i = 1; i <= 10; i++){
printf("%d ", a[i]);
}
printf("\n");
int b[] = {0, 4, 1, 3, 2, 16, 9, 10, 14, 8, 7};//注意以上函数中涉及的数组下标从1开始
build_max_heap(b, 10);
for(int i = 1; i<= 10; i++){
printf("%d ", b[i]);
}
int c[] = {0, 7, 8, 9, 10, 2, 3, 1, 4, 16, 14};//注意以上函数中涉及的数组下标从1开始
heapsort(c,10);
printf("\n");
for(int i = 1; i <= 10; i++){
printf("%d ", c[i]);
}
}
过程讲解见算法导论