堆排序和TOP-K问题

Posted 银背欧尼酱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆排序和TOP-K问题相关的知识,希望对你有一定的参考价值。


前言

1. 建堆的时间复杂度

  1. 快速排序(快排)O(NlogN)

  2. 以插入的方式建堆O(NlogN)

  3. 向下调整来建堆O(N)

2. 堆的排序

堆排序即利用堆的思想进行排序。

步骤:

1.建堆,排升序建大堆,排降序建小堆

2.排序 -->利用堆删除的思想排序。即先让头尾结点交换,再把堆中元素个数减1,将交换后的二叉树(此时已经不是堆了)利用向下调整法重新变成堆。循环往复。直到排好整个数组。

代码实现

//向下调整
void HeapAdjust(int array[], int size, int parent)
{
	int child = parent * 2 + 1;

	while (child < size)
	{
		if (child+1 < size && array[child + 1] > array[child])
			child += 1;

		if (array[child] > array[parent])
		{
			int temp = array[child];
			array[child] = array[parent];
			array[parent] = temp;

			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			return;
		}
	}
}


void HeapSort(int array[], int size)
{
	int end = size-1;
	// 1.建堆  升序-->大堆  降序-->建小堆
	for (int root = (size - 2) / 2; root >= 0; root--)
	{
		HeapAdjust(array, size, root);
	}

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

3. TOP-K问题

TOP-K问题即给出一组庞大的数据,要求找出数值最大或最小的前K个数。

如果用常规的排序算法,时间复杂度为O(N^2),时间复杂度过大。所以这里使用的思想来解决。

步骤(此处举例取数值最大的K个数):

  1. 用K个元素建小堆,因为是取最大的数。
  2. 使用剩余的N-K个数和堆顶元素比较,如果大于堆顶元素,则替换掉堆顶,并用向下调整法把数列重新调整为小堆。
  3. 这样做可以不断地让堆中最小的数值出局。当用N-K个元素依次和堆顶比较替换后,堆中的元素就是原数据组中最大的K个元素。

时间复杂度:

建堆的时间复杂度:O(K)。

剩余N-K个元素每次都向下调整:O(N-K)*log(K)。

所以总的时间复杂度为O(N);

代码实现参考上面的建堆和堆调整的代码即可。

总结

以上就是今天要讲的内容,介绍了几种建堆方法的时间复杂度,和利用堆排序的思想。配合博客《堆的初始化及增删查改等操作》食用更佳。

以上是关于堆排序和TOP-K问题的主要内容,如果未能解决你的问题,请参考以下文章

[ 数据结构 -- 手撕排序算法第七篇 ] 堆排序(下)用堆排序来解决Top-K问题

算法篇利用堆高效解决大数据量时TOP-K问题

堆 与 堆排序

堆 与 堆排序

堆 与 堆排序

上校教你如何用堆解决Top-K问题