堆排序--排序村的上忍

本文详细介绍了堆排序的原理,包括堆的概念、向上调整和向下调整算法,以及堆排序用于解决topk问题的方法。强调了堆排序的时间复杂度为O(Nlog2N),并与其他排序算法进行比较。
摘要由CSDN通过智能技术生成

堆排序

堆的概念

堆本身可以是一个数组,关键在于我们将其看成一个二叉树结构。比如下面
将数组看成二叉树

核心在于利用二叉树的结构特点:即根结点为最大值或最小值,来进行排序。

注:大堆:父亲比孩子大的堆。小堆反之。

堆排序(默认小堆,大堆同理)

向上调整算法

向上调整是指,对一个数据a要插入一个小堆,要不断向上与父节点比较,比父亲小则与之交换,并继续往上比较;由于默认除了a之外已是小堆,故若比父亲大则无需继续比较。如此,插入a后,小堆仍为小堆。

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

向下调整算法

向下调整则与前者相反。是指,对于小堆中的数据a,与其两个子节点较小的那一个比较,比孩子大则与之交换;由于已经是小堆,比孩子小则停下即可。

void AdjustDown(int* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child] > a[child + 1])
		{
			child++;
		}
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
			break;
	}
}

堆排序的原理(小堆对应降序)

堆排序实际上很巧妙。我们通过将堆顶数据与最后一个数据(即数组的最后一个)交换,实现将最小数放在数组末尾。再将前n-1个数据重新建堆,再重复前面过程,便实现了数组从大到小排列,而且不消耗额外空间。

堆排序的代码附上

void HeapSort(int* a, int n)
{
	for (int i = 0; i < n; i++)//先向上调整建堆
	{
		AdjustUp(a, i);
	}
	//for (int i = (n - 1) / 2; i >= 0; i--)//此为向下调整建堆
	//{
	//	AdjustDown(a, n, i);
	//}
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		end--;
	}
}

堆排的时间复杂度

  1. 首先建堆部分:如果是向上调整,则是一个等比数列:对于第k层,有2k-1个节点,最坏每个都需要向上挪动k-1次。从第一层累加到第h(堆的高度)层即可。又满二叉树h与N的关系:2h-1=N。结论是O(Nlog2N);向上调整建堆时间复杂度
    如果是向下调整建堆,因为只需从倒数第二层开始调整,所以是对2k-1乘(h-k),k从1到h-1累加即可,结论是O(N)。
    向下调整建堆时间复杂度
  2. 向下调整排序部分:第k层交换需要2k-1次,每次向下调整最坏需要调k-1次。则计算过程与向上调整建堆的一样。均为O(Nlog2N)。

综上,堆排时间复杂度为O(Nlog2N),与快排,希尔属同一段位。

堆的应用----top k问题

问:如何在N(比如1亿)个数据里选取最大的(或最小的)k个数,k远小于N。
答:当然是堆排了!假设选最大的,只需建立有k个数的小堆,遍历一遍数组,遇到比堆顶元素大的数据就把堆顶换成该数据,再向下调整小堆,最终堆里面留下的就是top大的k个数。

关于时间复杂度,遍历需要N,建堆应该为klog2k,因为k<<N,故O(N)=N。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值