从堆到堆排序

前言

每个排序方法的速度都有各异,其中,堆排序算是顶流,速度相当的快,但也相对难理解点,这篇文章将想你讲解从堆的建立到堆排序

一、堆是什么?

堆就是一种特殊的队列

堆是由二叉树延伸出来的,而二叉树又是从顺序表(数组)转化过来的

数组本来就是数组,但是有大佬把数组想象成了二叉树,然后又接着在二叉树的基础上搞出了堆,堆就可以衍生出很多技巧和方法

二、建堆方法

1.向上建堆法

向上建堆法原理就是将要导入的数组依次插入到新的数组中,但是每插入一次都顺便向上调整一次

图解如下:
在这里插入图片描述
示例代码:

void UpAdjust(int* arr, int child)
{
	
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (arr[child] > arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			child = parent;
			parent = (parent - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

2.向下建堆法

向下建堆的原理就是可以将某棵已经建的差不多的树(只剩堆顶没调整)建成完整的堆,前提是这棵树下面就是堆(适合原地建堆)

图解如下:
在这里插入图片描述

示例代码:

//向下调整
void DownAdjust(int* arr, int size, int parent) //size为
{
	int child = parent * 2 + 1;

	while (child < size)
	{
		//找出两个孩子中最小的
		if (child + 1 < size && arr[child + 1] > arr[child])
		{
			child++;
		}

		if (arr[parent] < arr[child])
		{
			Swap(&arr[parent], &arr[child]);
			parent = child;
			child = child * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

三、堆排序的方法

(建大堆为升序,建小堆为降序)
(前提是得先有堆)

换位法:

  • 将堆顶的数都放在最后面,已经放了的就不用管了
  • 一开始size个元素的堆,将堆顶元素和最后一个元素交换(最后一个元素不用再参与调整),然后这size-1个元素再调整出新的堆(向上或者向下建堆法都可以),再把堆顶元素和最后一个元素交换,直到size = 1;
  • 利用堆顶的元素为最值这一特点,将最值依次放到队尾,便达到了排序的作用

图解如下:

在这里插入图片描述

示例代码:

//堆排序
void HeapSort(int* arr, int size)
{
	assert(arr);
	assert(size != 0);
	//先建一次堆
	for (int i = 1; i < size; i++)
	{
		UpAdjust(arr, i);
	}
	//此时已经有最大的数了

	//利用向下调整法,将之后次大的数放到最后面
	while (size > 1)
	{
		//size就是数组的个数
		Swap(&arr[0], &arr[size - 1]);//arr[size - 1]就是数组最后一个元素
		//当最大的那个数已经被放到最后面的时候,要调整的个数就变成了size-1
		DownAdjust(arr, size - 1, 0);//向下调整中的size-1代表的是,你要调整的数据个数,并不是数组最后一个下标
		size--;
	}
}

总结

以上就是今天要讲的内容,本篇文章着重讲解了两个建堆方法以及堆排序的原理和思路,在力扣以及牛客网中还会有很多类似的题目,今后将会持续更新,敬请关注!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值