排序之堆排序

堆排序

基本思想:

        堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是

排升序要建大堆,排降序建小堆 ,利用堆删除的思想进行排序

 向下调整: 条件---->在调整某个节点时,必须保证该节点的左右子树已经满足堆的性质

void AdjustDown(int array[] , int size, int  parent)
{
    //
用child标记parent较大的孩子,parent可能有左没有右孩子
    int child = parent * 2 + 1;

    while (child < size) 
        1.如果右孩子存在的情况下,找较小的孩子,并用child进行标记
        2.检测parent是否满足堆的性质,与child的大小关系

        if (array[child] > array[parent])

        小:需要将双亲与孩子节点中的元素进行交换,为了防止调整后子树堆的性质被破坏掉,然  后继续向下调整   

                parent = child;   child = parent * 2 + 1;

        大:parent节点已经满足大堆的特性------>直接返回

}

堆删除:每次删除堆顶元素

        Ⅰ.检测堆是否为空,堆为空直接返回,否则进行Ⅱ

        Ⅱ.将堆顶元素与堆中最后一个元素进行交换,将堆中有效元素个数减1 对堆顶元素进行向下调整     

void Swap(int* left, int* right)
{
	int temp = *left;
	*left = *right;
	*right = temp;
}

// 建堆,向下调整法
void HeapAdjust(int array[], int size, int parent)
{
	// 用child标记parent较大的孩子,默认先标记parent的左孩子
	// 先标记左孩子的原因是:如果parent有孩子,parent一定是先有左孩子,然后才有右孩子
	int child = parent * 2 + 1;

	while (child < size)
	{
		// 找parent中较大的孩子:用parent左右孩子比较
		// 必须先保证parent的右孩子存在
		if (child+1 < size && array[child + 1] > array[child])
			child += 1;

		// 检测parent是否满足大堆的性质
		if (array[child] > array[parent])
		{
			Swap(&array[child], &array[parent]);
            // 交换后可能导致子树不满足堆的性质,所以需要继续向下进行
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			return;
		}
	}
}



// 堆排序(选择排序的一种)
// 时间复杂度:O(NlogN)
// 空间复杂度:O(1)
// 稳定性:不稳定
void HeapSort(int array[], int size)
{
	int end = size - 1;
	// 1. 建堆
	// 注意从倒数第一个非叶子节点的位置开始使用堆调整,一直减减,调整到根节点的位置
	for (int root = (size - 2) / 2; root >= 0; root--)
		HeapAdjust(array, size, root);  // 向下调整---时间复杂度:O(logN)

	// 2. 排序--->利用堆删除的思想进行排序
	while (end)
	{
		Swap(&array[0], &array[end]);
		HeapAdjust(array, end, 0);
		end--;
	}
}

 堆排序的特性总结:

        1. 堆排序使用堆来选数,效率就高了很多。

        2. 时间复杂度:O(N*logN)

        3. 空间复杂度:O(1)

        4. 稳定性:不稳定

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值