给下面链接上的堆排序加了一点点自己的注释,菜鸡瑟瑟发抖
参考文献 http://blog.youkuaiyun.com/lzuacm/article/details/52853194
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
//堆排序(最大堆-从小到大排序)
/*
主要的步骤是adjust函数
我喜欢下面这种写法,数据结构上那本书上的写法用的while循环,不如用递归写的好
*/
void adjust(int arr[], int len, int index)
{
//index:当前要调整的节点的位置
int left = 2*index + 1;//左子树的根节点
int right = 2*index + 2;//右子树的根节点
int maxIdx = index;//现在下面两个if,其实就是找当前节点,左子树的根节点,右子树的根节点三者中的最大者
//为什么要这样做呢,首先堆排序的默认前提是左子树和右子树都是默认成了最大堆,但是整体上,即把当前节点和它
//的左子树和右子树合在一起看就不一定是大顶堆了,此时便要分三种情况,其实是两种情况
//情况1.--如果当前节点碰巧就比左子树的根节点的值大,也比右子树的根节点的值大,那么就不用调整了,对应代码中的
//maxIdx==index,就不调整了
//情况2.--如果当前节点比某一个子树的根节点小(可能比两个子树的根节点都要小,但是maxIdx一定指向最大的,后面
//交换了当前节点与最大值的节点之后,现在当前节点变成最大了,其中某一个子树就不用再调整了,这样就加快了速度
//但这是一个递归的过程,即交换后的子树节点不构成堆,所以递归就可以了
if(left<len && arr[left] > arr[maxIdx]) maxIdx = left;
if(right<len && arr[right] > arr[maxIdx]) maxIdx = right; // maxIdx是3个数中最大数的下标
if(maxIdx != index) // 如果maxIdx的值有更新
{
swap(arr[maxIdx], arr[index]);
adjust(arr, len, maxIdx); // 递归调整其他不满足堆性质的部分
}
}
//最大堆,堆顶是数组的最大值
void heapSort(int arr[], int size)
{//
for(int i=size/2 - 1; i >= 0; i--) // 对每一个非叶结点进行堆调整(从最后一个非叶结点开始)
{//因为开始的时候,给的是一个很无序的数组,所以需要从size/2-1向下调整多次
adjust(arr, size, i);//首先建堆的时候不是调整一次,要调整多次
}//之后的调整都是调整一次,因为此时已经有了大致的堆结构,最后只有一条路径有问题
for(int i = size - 1; i >= 1; i--)
{
swap(arr[0], arr[i]); // 将当前最大的放置到数组末尾,所以输出的时候是从小到大输出
adjust(arr, i, 0); // 将未完成排序的部分继续进行堆排序
}
}
int main()
{
int array[8] = {8, 1, 14, 3, 21, 5, 7, 10};
heapSort(array, 8);
for(auto it: array)
{
cout<<it<<endl;
}
return 0;
}
#巴啦啦
```
[1]: http://blog.youkuaiyun.com/lzuacm/article/details/52853194