对大根堆的理解

首先:将数组看成树,由于大根堆输出的元素是由小到大的,每次调整堆,都将根元素(即最大的元素)移到叶节点处

(我的理解是,大根堆只是刚开始根的最大的,一次递归将最大元素放到叶节点之后,根元素是最小元素,输出类似按树的每一层输出)

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

 

 

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