對大根堆的理解

首先:將數組看成樹,由於大根堆輸出的元素是由小到大的,每次調整堆,都將根元素(即最大的元素)移到葉節點處

(我的理解是,大根堆只是剛開始根的最大的,一次遞歸將最大元素放到葉節點之後,根元素是最小元素,輸出類似按樹的每一層輸出)

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;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章