时间复杂度为O(nlogn)
将数组堆化,改成小顶堆(本例)
void minheap(int ar[]) {
int length = sizeof(ar) / sizeof(int);
//从右往左,自下而上
//一半的位置是合法的最小堆
for (int i = length / 2 - 1; i >= 0; i--) {
mintree(ar, i, length-1);
}
}
//下面的递归是从小向大,自上而下
void mintree(int ar[],int i, int b) {
//左右孩子
int left = i * 2 + 1;
int right = i * 2 + 2;
//探讨下标越界的情况,并把min赋给可能的左右孩子
//如果左孩子越界,那么i就是叶子节点
if (left >= b) {
return;//左孩子下标越界,那么右边肯定也越界了,所以不用调整了
}
int min = left;//把min初始化为left,方便
//如果右孩子越界,那么就剩左孩子,所以左孩子就是叶子节点
if (right >= b) {
min = left;//于是就把left赋给min,即left直接与i比较
}
//如果左右孩子都没越界,
else {
//比较左右孩子即可
if (ar[right] < ar[left]) {
min = right;
}
}
//将上面获得的min与i位置的数比较
//如果i比小孩子小,就不用换
if (ar[i] < ar[min]) {
return;
}
int temp = ar[i];
ar[i] = ar[min];
ar[min] = temp;
//进行递归解决由于刚才弄i所造成的损失
//小孩子那个位置(被换的那面)的值发生了变化,所以i变为小孩子
mintree(ar, min, b);
}
//进行排序
void sort(int ar[],int b) {
//先把数组堆化
minheap(ar,b);
//对第一个元素与最后一个元素值调换
for (int i =b; i >= 0;i--) {
swap(&ar[0], &ar[b]);//进行调换
//缩小堆的范围,对堆顶元素向下调整
mintree(ar, 0, b);//从0号开始向下修正
}