1. 程式人生 > >大資料處理堆實現N個數據找K個最大資料和堆排序

大資料處理堆實現N個數據找K個最大資料和堆排序

在N個數據中找K個最大資料思想:用堆實現找最大的資料,則先建立一個N個數據中其前K個節點的最小堆,將沒進入最小堆的節點依次與小堆的頭節點比較,若大於頭節點,則替換兩個值,並且呼叫向下調整演算法(其思想前面部落格已經介紹實現),直到N個數據比較完成,此時最小堆中的K個節點即為N個數據中的K個最大資料。

在程式碼中為了方便測試N與K的值較小。

堆排序思想:即建立一個堆來實現排序,升序與降序思想基本相同,這裡介紹降序,要降序則先建立一個最小堆後,則每次將最小堆頭節點與尾節點值交換,即最後一個節點為最小值,此時除去最後一個節點,在剩下範圍呼叫向下調整演算法,在依次用相同方法實現直至範圍只剩下一個節點即為最大的一個節點。此時則排序完成。

程式碼實現:

#include <iostream>
#include <cstdlib>
#include <assert.h>
using namespace std;
void AdjustDown(int* a,size_t k,size_t i)  //向下調整
{
	assert(a);
	size_t parent=i;
	size_t child=i*2+1;
	while(child<k)
	{
		if(child+1<k&&a[child+1]<a[child])
			++child;
		if(a[child]<a[parent])
		{
			swap(a[child],a[parent]);
			parent=child;
			child=parent*2+1;
		}
		else
			break;
	}
}

void GetTopK(int* a,int* TopK,size_t n,size_t k) //N個數據找最大的前K個
{
	for(size_t i=0;i<k;++i)
	{
		TopK[i]=a[i];
	}
	//先找第一個非葉子結點,依次向下調整建小堆
	for(int i=(k-2)/2;i>=0;--i)
	{
		AdjustDown(TopK,k,i);
	}
	//選最大的前K個數據
	for(size_t i=k;i<n;++i)
	{
		if(a[i]>TopK[0])
		{
			TopK[0]=a[i];
			AdjustDown(TopK,k,0);
		}
	}
}

void HeapSort(int a[],size_t n)  //堆排序:降序
{
	//建小堆
	for(int i=(n-2)/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;
	}
}
void TestNK()
{
	const int N=1000;
	const int K=5;
	int a[N]={0};  //儲存N個數據
	int TopK[K]={0};  //儲存K個最大資料
	for(size_t i=0;i<N;++i)
	{
		a[i]=rand()%N;
	}
	a[10]=1000;
	a[100]=2000;
	a[200]=3000;
	a[300]=4000;
	a[400]=5000;

	GetTopK(a,TopK,N,K);
	for(size_t i=0;i<K;++i)
	{
		cout<<TopK[i]<<" ";
	}
	cout<<endl;
}

void TestHeapSort()
{
	int a[]={19,17,18,14,16,13,15,12,10,11};
	HeapSort(a,sizeof(a)/sizeof(a[0]));
}

int main()
{
	TestNK();
	TestHeapSort();
	system("pause");
	return 0;
}