利用最大堆和最小堆求海量数据的前n大/前n小/Top k问题

版权声明:转用请注明出处 https://blog.csdn.net/weixin_39411321/article/details/89208219

海量数据求top k的问题要用到容器和堆

大根堆(求最小的前n个数)

小根堆(求最大的前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;
	}

运行结果如下:
在这里插入图片描述

备注:本来想用更大的数据 但是电脑运行太慢了 半天跑不出来 所以挑了个小一点的数字

猜你喜欢

转载自blog.csdn.net/weixin_39411321/article/details/89208219