100w个数中找出最大的前K个数

100w个数中找出最大的前K个数这个题是堆应用

首先100万个数大约占4M内存,可以加载到内存中。我们可以采用排序解决这个问题,比如堆排序、快排等,但排序不是最优解。我们可以利用最小堆来解决这个问题。

堆数据结构是一种数组对象,它可以被视为一棵完全二叉树结构。
堆结构的二叉树存储是
最大堆:每个父节点的都大于孩子节点。
最小堆:每个父节点的都小于孩子节点。
思路:1、开辟大小为k的空间,把数组中前k个数建小堆
           2、把剩下的数依次和堆顶元素进行比较,如果后面的数大于堆顶,替换掉堆顶,重新调整为最小堆,直到把剩下的数与堆顶比较完,此时堆里的k个数就是最大的前k个数
#include<iostream>
using namespace std;

void _Adjustdown(int* arr, int size, int parent)
{
	int child = parent * 2 + 1;
	while (child < size)
	{
		//比较左右节点,选择较小的
		if (child + 1 < size && arr[child] > arr[child + 1])
		{
			child++;
		}
		if (arr[parent] > arr[child])
		{
			swap(arr[parent],arr[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
//建小堆
void BuildHeap(int *arr,int size)
{
	//从第一个非叶子节点开始向下调整
	for (int i = (size-2)/ 2; i >= 0; --i)
	{
		_Adjustdown(arr, size, i);
	}
}
void GetKTop(int* arr,int size,int k)
{
	if (size<k || k<=0)
	{
		return;
	} 
	//开辟大小为k的空间,把数组中前k个数建小堆
	int *heap = new int[k];
	for (int i = 0; i < k; ++i)
	{
		heap[i] = arr[i];
	}
	BuildHeap(heap,k);

	//把后面的数依次和堆顶比较
	for (int i = k; i<size; ++i)
	{
		//如果后面的数大于堆顶,替换掉堆顶,重新调整为最小堆
		if (arr[i]>heap[0])
		{
			heap[0] = arr[i];
			_Adjustdown(heap, k, 0);
		}
	}

	for (int i = 0; i < k; ++i)
	{
		cout << heap[i] << " ";
	}
	
	delete[] heap;
}
int main()
{
	int arr[] = {1,2,5,6,7,9,2,5,10,22,40,35};
	int size = sizeof(arr) / sizeof(arr[0]);
	GetKTop(arr,size,3);
	return 0;
}

 

如果用堆排序解决问题,需要把所有数进行建堆,建堆的时间复杂度O(lgN),如果只把前k个数建堆,时间复杂度O(lgk),k远小于N,效率比堆排序高。


 

 

 

你可能感兴趣的:(堆应用)