topK問題——N個數中取最大的K個數

topK問題

在海量數據中找出出現頻率最高的前k個數,或者從海量數據中找出最大的前k個數,這類問題通常被稱爲topK問題

N個數中取最大的K個數,用小根堆;N個數中取最小的K個數,用大根堆;時間複雜度O(NlogK)。

例題1100萬個數中,找到其中最大的100個數。(N個數中取最大的K個數)

思路:

(1) 定義兩個數組,arr用於存儲海量數據N,top用於存儲小根堆K;

(2) 將海量數據的前K個元素先填滿top堆;

(3) 調整top堆爲最小堆結構;

(4) 通過遍歷將新數據與堆頂元素(此時堆頂元素最小)比較,大於堆頂元素就入堆,並下調堆結構。

(5) 遍歷結束,則堆中的元素即N個數中最大的前K個數。

代碼如下:

#include<iostream>
#include<cassert>
#include<ctime>

using namespace std;

const int N = 100000;
const int K = 10;

void adjustDown(int *top, int i)
{
	int child = 2 * i + 1;
	int min = i;
	while (min < K/2)
	{
		if (child + 1 < K&&top[child] > top[child + 1])
			child++;
		if (child<K&&top[min]>top[child])
		{
			swap(top[min], top[child]);
			min = child;
			child = 2 * min + 1;
		}
		else
			break;
	}
}

void topK(int *arr, int *top)
{
	assert(arr != nullptr&&top != nullptr);
	for (int i = 0; i < K; i++)
	{
		top[i] = arr[i];
	}
	for (int i = K / 2 - 1; i >= 0; i--)
	{
		adjustDown(top, i);
	}
	for (int i = K; i < N; i++)
	{
		if (arr[i]>top[0])
		{
			top[0] = arr[i];
			adjustDown(top, 0);
		}
	}
	for (int i = 0; i < K; i++)
		cout << top[i] << " ";
	cout << endl;
}

int main()
{
	int arr[N];
	int top[K];
	srand((unsigned)time(0));//隨機種子
	for (size_t idx = 0; idx < N; ++idx)
	{
		arr[idx] = rand() % 10000;
	}
	topK(arr, top);
	return 0;
}


發佈了55 篇原創文章 · 獲贊 25 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章