利用最大堆和最小堆求海量數據的前n大/前n小/Top k問題

一、海量數據的前n大/前n小/Top k問題

海量數據求top k的問題要用到容器和堆

二、大根堆/小根堆

1、大根堆(求最小的前n個數)

2、小根堆(求最大的前n個數)

堆的實質其實就是一顆完全二叉樹

最大堆特點:父節點值均大於子節點;(堆頂元素最大)

最小堆特點:父節點值均小於子節點;(堆頂元素最小)

總結:找top最大的用小根堆;找top最小的用大根堆

三、最大堆找top k小代碼的基本思路

求前n個最小的數 先建立最大堆 把海量數據向最大堆添加n個數,然後堆的內部會自動排序 我們不用管它的內部是怎麼操作的 接下來我們往最大堆進行插入操作 因爲最大堆的特點就是堆頂元素最大 若插入元素大於堆頂元素 則它大於堆中任何一個元素 所以摒棄該元素 遍歷下一個元素 若插入元素小於堆頂元素則進行插入 插入後堆內自動排序 堆頂元素又成爲該堆的最大元素 原堆頂元素出堆 持續遍歷完 得到的就是所有元素中最小的前n個數

四、最小堆找top k大代碼的基本思路

求前n個最大的數 先建立最小堆 把海量數據向最小堆添加n個數,堆的內部會自動排序 不用管它的內部是什麼操作 然後我們往最小堆進行插入操作 因爲最小堆的特點就是堆頂元素最小 若插入元素小於堆頂元素 則它小於堆中任何一個元素 所以摒棄該元素 遍歷下一個元素 若插入元素大於堆頂元素則進行插入 插入後堆內自動排序 堆頂元素又成爲該堆的最小元素 原堆頂元素出堆 持續遍歷完 得到的就是所有元素中最大的前n個數

五、源代碼

int main()
{
	//在最短時間內找到所有整數中最大/最小的n個數並且打印;
	//找top最大的用小根堆;找top最小的用大根堆
	//時間複雜度 O(n)*log2 n
	//===================最大堆找最小值======================
	vector<unsigned int>vec;
	for (unsigned int i = 0; i < 20000; ++i)
	{
		vec.push_back(rand() + i); //隨機產生兩萬個數據放在vector容器中
	}
	priority_queue<int> maxHeap; //聲明最大堆
	int k = 10;//求20000個數據中前10小個數
	for (int i = 0; i < k; i++)
	{
		maxHeap.push(vec[i]);//先往最大堆中放10個數
	}
	for (int i = k; i < 20000; ++i)
	{
	    //遍歷判斷容器中剩餘的每個數與堆頂元素的大小
	    //若小於堆頂元素 則把堆頂元素出堆 把該元素入堆
		if (vec[i] < maxHeap.top())
		{
			maxHeap.pop();
			maxHeap.push(vec[i]);
		}
	}
	while (!maxHeap.empty())
	//打印最大堆裏邊的十個最小的數
	{
		cout << maxHeap.top() << " ";
		maxHeap.pop();
	}
	cout << endl;

//==========================================================
//==========================最小堆找最大值===================
	for (unsigned int i = 0; i < 20000; ++i)
	{
		vec.push_back(rand() + i);
	}
	priority_queue<int, vector<int>, greater<int>> minHeap; //建立最小堆
	//注意:最小堆要加上greater<int>
	int j = 10;
	for (int i = 0; i < j; i++)
	{
		minHeap.push(vec[i]);
	}
	for (int i = j; i < 20000; ++i)
	{
	    //遍歷判斷容器中剩餘的每個數與堆頂元素的大小
	    //若大於堆頂元素 則把堆頂元素出堆 把該元素入堆
		if (vec[i] > minHeap.top())
		{
			minHeap.pop();
			minHeap.push(vec[i]);
		}
	}
	while (!minHeap.empty())
	{
		//打印最大堆裏邊的十個最小的數
		cout << minHeap.top() << " ";
		minHeap.pop();
	}
	cout << endl;
	return 0}

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