1. 程式人生 > >面試題: 求N個數中前k個大的數(大資料)

面試題: 求N個數中前k個大的數(大資料)

解題思路:一般思路就是將N個數排序後,取前k個數就ok。但是如果N個數是幾十億個數,載入不到記憶體怎麼辦?這就需要另外一種思路了,那就是利用堆。

具體的思路是:先建一個k個數的小堆,然後從k+1個數往後的值與堆頂元素比較,若此數比堆頂元素大,就將堆頂元素用這個數替換,然後重新調整堆,以此向後重複上述過程,直到將N個數比較完成,那麼此時組成這個堆的k個元素就是前k個大的數。

下邊是具體實現的程式碼:

#pragma once 
#include<iostream>
#include<vector>
using namespace std;
template<class T>
class Heap
{
	public:
	Heap(const T* a, int k)
	{
		_CreateHeap(a, k);
	}

	void Push(const T& x)
	{
		_a.push_back(x);
		_AdjustUp(_a.size() - 1);
	}

	T& Top()
	{
		return _a[0];
	}

	void BuildHeap(const T* a, int k)
	{
		for (int i = (k - 2) / 2; i >= 0; i--)
		{
			_AdjustDown(i);
		}
	}

	void Print()
	{

		for (int i = 0; i < _a.size(); i++)
		{
			cout << _a[i] << " ";
		}
		cout << endl;
	}

public:
	void _CreateHeap(const T* a, int k)
	{
		for (int i = 0; i < k; i++)
		{
			_a.push_back(a[i]);
		}

		//建小堆
		for (int i = (k - 2) / 2; i >=0; i--)
		{
			_AdjustDown(i);
		}
	}

	
	void _AdjustDown(int parent)	//向下調整
	{
		int child = parent * 2 + 1;
		while (child < _a.size())
		{
			if (child + 1 < _a.size() && _a[child] > _a[child + 1])
			{
				child++;
			}
			if (_a[child] < _a[parent])
			{
				swap(_a[child], _a[parent]);
				parent = child;
				child = parent * 2 + 1;
			}
			else
			{
				break;
			}
		}
	}
	//void _AdjustUp(int child)//向上調整
	//{
	//	int parent = (child - 1) / 2;
	//	while (child >= 0)
	//	{
	//		if (_a[child] > _a[parent])
	//		{
	//			swap(_a[child], _a[parent]);
	//			child = parent;
	//			parent = (child - 1) / 2;
	//		}
	//		else
	//		{
	//			break;
	//		}
	//	}
	//}

private:
	vector<T> _a;
};
#include"HeapSort.h"

void GetTopK(int* a, int k, int size)
{
	//建堆
	Heap<int> hp(a, k);
	//hp.Print();
	//k個數後面的數,比堆頂元素大,則插入
	for (int i = k; i < size; i++)
	{
		if (hp.Top() < a[i])
		{
			hp.Top() = a[i];
			hp._AdjustDown(0);
		}
	}
	hp.Print();
}

void Test()
{
	int a[] = { 1, 0, 3, 5, 8, 2, 6, 7, 4, 9, 10, 26, 35, 20, 30, 40 };
	int len = sizeof(a) / sizeof(a[0]);
	int k = 6;
	for (int i = 0; i < len; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;
	cout << "最大的前" << k << "個數為:" << endl;
	GetTopK(a,6,len);
}