首先:将数组看成树,由于大根堆输出的元素是由小到大的,每次调整堆,都将根元素(即最大的元素)移到叶节点处
(我的理解是,大根堆只是刚开始根的最大的,一次递归将最大元素放到叶节点之后,根元素是最小元素,输出类似按树的每一层输出)
eg:结果如下所示 初始---------------------------------->初建堆(大根堆)--------------------------------->结果
例如:最大的元素与最后一个叶节点互换,第二大的元素与倒数第二个叶节点互换。。。。以此类推
最大的元素与最后一个叶节点互换之后,进行一次由上到下的堆排序,将第二大的元素提到根结点中。。。。以此类推
步骤:1、初建堆:由下到上构造大根堆,确保每个结点都大于其左、右结点
2、调整堆:将树中最后一个元素与根结点互换,再由上到下构造新的大根堆
将树中倒数第二个元素与根结点互换,由上到下构造新的大根堆。。。以此类推
3、输出数组即为单调递增的数组
参考文章:https://www.cnblogs.com/wangchaowei/p/8288216.html
https://www.cnblogs.com/wanglei5205/p/8733524.html
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<stack>
using namespace std;
// 递归方式构建大根堆(len是arr的长度,index是第一个非叶子节点的下标)
void adjust(vector<int> &arr, int len, int index)
{
int left = 2 * index + 1; // index的左子节点
int right = 2 * index + 2;// index的右子节点
int maxIdx = index;
if (left<len && arr[left] > arr[maxIdx]) maxIdx = left;
if (right<len && arr[right] > arr[maxIdx]) maxIdx = right;
if (maxIdx != index)//就是本身的话,不用调整
{
swap(arr[maxIdx], arr[index]);
adjust(arr, len, maxIdx);
}
}
// 堆排序
void heapSort(vector<int> &arr, int size)
{
// 构建大根堆(从最后一个非叶子节点向上)
for (int i = size / 2 - 1; i >= 0; i--)
{
adjust(arr, size, i);
}
// 调整大根堆
for (int i = size - 1; i >= 1; i--)
{
swap(arr[0], arr[i]); // 将当前最大的放置到数组末尾
adjust(arr, i, 0); // 将未完成排序的部分继续进行堆排序
}
}
int main()
{
//大根堆输出的是从小到大的序列
vector<int> arr = { 8, 1, 14, 3, 21, 5, 7, 10 };
heapSort(arr, arr.size());
for (int i = 0; i < arr.size(); i++)
{
cout << arr[i] << endl;
}
system("pause");
return 0;
}