首先:將數組看成樹,由於大根堆輸出的元素是由小到大的,每次調整堆,都將根元素(即最大的元素)移到葉節點處
(我的理解是,大根堆只是剛開始根的最大的,一次遞歸將最大元素放到葉節點之後,根元素是最小元素,輸出類似按樹的每一層輸出)
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;
}