【算法】Python & C++实现排序算法(五)之堆排序

1、堆排序
https://blog.csdn.net/u010452388/article/details/81283998?
堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。【类似于现实中的叠罗汉】

2、具体分析
堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。【大顶堆】【小顶堆】
什么是完全二叉树? 】特点在于:
1、从作为第一层的根开始,除了最后一层之外,第N层的元素个数都必须是2的N次方;第一层2个元素,第二层4个,第三层8个,以此类推。
2、而最后一行的元素,都要紧贴在左边,换句话说,每一行的元素都从最左边开始安放,两个元素之间不能有空闲,具备了这两个特点的树,就是一棵完全二叉树。
基本思想:

1.首先将待排序的数组构造成一个大(小)根堆,此时,整个数组的最大值就是堆结构的顶端

2.将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1

3.将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组
在这里插入图片描述可以看到对于序列【3,6,8,5,7】:
第一轮中起点为array[1],将其与自己子节点比较并交换,a[1]得到目前最大的数值。继续第二轮起点为a[0],同样将其与自己子节点比较,a[0]得到最大值。此时完成一次大顶堆排序。【注意:我们每一次把无序序列构造成大顶堆,目的是为找出该序列中的最大值,并把它存储在a[0],所以我们每次只关心根节点是不是全局最大就可以,对于整个二叉树是不是一个完全满足大顶堆条件这不重要,这是什么意思呢?简而言之,即只保证每轮中根节点为最大就可以,对于中间层的父节点是否满足大顶堆的“父节点》=子节点”条件不需要考虑】

3、代码实现

/*
作者:kimicr
时间:20200327
功能:堆排序
特点:不稳定且时间复杂度【nlogn】
*/
#include"iostream"
#include"Sort.h"
using namespace std;

void HeapBig_Node(int *array, int father, int length)
{
    
    
	/*
	这里的构建大顶堆需要注意:我们只关心最后根节点是不是最大的那个,而对于
	其他二叉树数据结构中父节点满不满足“父节点 >= 子节点”的大顶堆规则没有
	必要考虑。因此可以在这里成为我们构建的不是完美大顶堆,仅是泛化大顶堆。
	*/
	int temp = array[father];  //存储起始节点数字

	//将无序的序列调整为一个大顶堆
	for (int child = 2 * father + 1; child < length; child = 2 * child + 1)
	{
    
    
		if (child + 1 < length && array[child] < array[child + 1])   //若右边存在且,大于左边
			child++; //那么就转向右边

		if (temp < array[child]) //比较起始节点(父节点)与较大的子节点的大小关系
		{
    
    
			SWAP(array, father, child);   //交换,此时起始节点是以它为顶点的树中的最大值
			father = child;              //将旧的子节点(也是进行交换的子节点)作为下一轮的父节点
		}

		else
			break;
	}

}


void HeapSort(int *array, int length)
{
    
    
	// 第一步将无序序列变为大(小)顶堆
	// 自下而上的构建大顶堆
	for (int i = ((length - 1)-1) / 2; i >= 0; i--)
		HeapBig_Node(array, i, length);

		// 将最后的叶节点与得到的大顶堆顶点交换,并将剩余序列重复进行第一步操作
	for (int j = length-1; j >0; j--)
	{
    
    
		SWAP(array, 0, j);  //交换
		//由于交换大顶堆顶节点与树中的最后面节点,对于后面剩下序列的重新
		//大顶堆构建而言,只是顶节点产生了变化,所以只需要自上而下的对树
		//进行大顶堆构建就可以了。
		HeapBig_Node(array, 0, j);
	}
}
int main()
{
    
    
	int a[] = {
    
    20, 17, 8, 7, 16, 3};
	cout << sizeof(a) / sizeof(a[0]) << endl;  //ptint:length=7
	HeapSort(a, sizeof(a) / sizeof(a[0]));
	for (int i = 0; i < (sizeof(a)/sizeof(a[0])); i++)
		cout << a[i] << " ";
	cout << endl;
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_32643313/article/details/105173834