【海量數據處理】N個數中找出最大的前K個數

N個數中找出最大的前K個數,需要用小堆實現。

分析:由於小堆的堆頂存放堆中最小的數據,可以通過與堆頂數據進行比較,將大數據存放在堆中,注意在每次改變堆頂數據後,進行調堆,使堆頂一直存放整個堆中最小元素。

void AdjustDown(int *a, size_t root, size_t size)//下調
{//小堆
	size_t parent = root;
	size_t child = parent * 2 + 1;
	while (child < size)
	{
		if (child + 1 < size && a[child] > a[child + 1])
		{
			++child;
		}
		if (a[parent] > a[child])
		{
			swap(a[parent], a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else//注意不滿足交換條件時跳出本次循環
		{
			break;
		}
	}
void CreateRetPacket(vector<int>& moneys)//創建N個數
{
	srand((unsigned int)time(NULL));
	//srand(time(0));
	moneys.reserve(N);
	for (size_t i = 0; i<N; i++)
	{
		moneys.push_back(rand() % 1000);//產生N個隨機值
	}
	for (size_t i = K; i < N; ++i)
	{
		moneys[i] *= 100;
	}
}
void GetTopk(const vector<int>& moneys, int n, int k)//N個數中找最大的前k個數--小堆實現
{
	assert(n>k);
	int *TopkArray = new int[k];//通過前k個元素建立含有k個元素的堆
	for (size_t i = 0; i < k; i++)
	{
		TopkArray[i] = moneys[i];
	}
	for (int i = (k - 2) / 2; i >= 0; --i)//建小堆
	{
		AdjustDown(TopkArray, i, k);
	}
	//從第k個元素開始到第n個元素分別與堆頂元素進行比較,較大數據入堆頂,再對整個堆進行下調,使堆頂存放最小元素(小堆)
	for (size_t i = k; i < n; ++i)
	{
		if (moneys[i]  > TopkArray[0])
		{
			TopkArray[0] = moneys[i];
			AdjustDown(TopkArray, 0, k);
		}
	}
	size_t count = 0;
	for (size_t i = 0; i < k; ++i)//打印k個最大數據,即堆中所有元素
	{
		cout << TopkArray[i] << " ";
		++count;
		if (count % 10 == 0)
		{
			cout << endl;
		}
	}
	cout << endl;
	delete[] TopkArray;//注意釋放TopkArray所佔的內存
	TopkArray = NULL;
}

測試用例如下:

#include<iostream>
#include<assert.h>
#include<vector>//容器--類模板
#include<stdlib.h>//利用隨機值
#include<time.h>
using namespace std;

#define N 10000
#define K 100
void Test8()
{//N個裏面找最大的前k個數
	vector<int> moneys;
	CreateRetPacket(moneys);
	GetTopk(moneys, N, K);
}

上述可實現下列題:

    春節期間,A公司的支付軟件某寶和T公司某信紅包大亂戰。春節後高峯以後,公司Leader要求後臺的攻城獅對後臺的海量數據進行分析。先要求分析出各地區發紅包金額最多的前100用戶。現在知道人數最多的s地區大約有1000w用戶。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章