数据结构与算法_大数据处理_求topK的两种求解方法
创始人
2024-01-21 00:39:42

这篇笔记记录求大数据topk的两种方法,分别是大小二叉堆法和快速分割法,下面依次详解这两种方法的过程。

1 大/小根堆法

利用大根堆过滤前top k小的数据**;小根堆过滤前top k大的数据**;
下面用大根堆求前k个小元素为例。

  • 思想:
    把大根堆堆顶的大值不断的淘汰,放入小值。先构建k个元素的大小堆(比如k=3,就是求数列中前3个元素),然后用数列中的元素依次与堆顶元素比较,如果大于或者小于堆顶元素,就进行出堆调整;最后再进行入堆调整。
  • 过程
    先用数列中前k个元素构建一个堆,比如构建一个大根堆。新元素与堆顶元素比较,大于堆顶元素就进行下一个元素;如果新元素比堆顶元素小,堆顶元素先出堆,然后将新元素加入到堆中
    在这里插入图片描述

代码

#include 
#include 
#include 
#include 
#include 
using namespace std;int main()
{vector vec;srand(time(NULL));for (int i = 0; i < 10; i++){vec.push_back(rand() % 100);cout << vec[i] << " ";}cout << endl;// 求vec中值最小的前5个元素priority_queue maxheap;int k = 5;// 前5个元素入堆for (int i = 0; i < 5; i++){maxheap.push(vec[i]);}// 遍历剩余元素,直到最后for (int i = 5; i < vec.size(); i++){if (maxheap.top() > vec[i]){maxheap.pop();maxheap.push(vec[i]);}}// 输出结果  while (!maxheap.empty()){cout << maxheap.top() << " ";maxheap.pop();}cout << endl;

求出序列中值最大的前k个元素

	priority_queue, greater> minheap;// 前5个元素入堆for (int i = 0; i < 5; i++){minheap.push(vec[i]);}// 遍历剩余元素,直到最后for (int i = 5; i < vec.size(); i++){if (minheap.top() < vec[i]){minheap.pop();minheap.push(vec[i]);}}// 输出结果  while (!minheap.empty()){cout << minheap.top() << " ";minheap.pop();}

2 快排分割法

背景: 实际工作场景中经常遇到求topk的问题,比如找出最近人们搜索最多的商品,最多的应用等,多属于topk的问题,除了上面的利用大小根堆来求解topk问题之外,还可以利用快速排序思想求解topk问题。
**算法思想:**利用快速排序算法思想,判断快排分割函数每次返回的Pos值,如果pos值等于topk就直接返回,这样数组中从0到pos位置求出的就是前topk;如果pos大于或者小于topk,就继续求解。
算法步骤:
利用了快速排序的步骤。

在这里插入图片描述
在这里插入图片描述
算法性能分析:
平均时间复杂度:第一次找出一半的元素,第二次递归分割直达pos = K-1 ;一共N个元素,平均结果如下:
O(n)=N + N/2 +N/4 + … + 1 = 2N = O(n)
**最坏情况下时间复杂度:如果原始数列是有序的,比如从小到大的排列的,这时候求最大的top1时候,时间复杂度如下:
N +(N-1) + (N-2) +(N -3) + … + 1 = O(N2)=**O(n2)

在这里插入图片描述

代码

#include 
#include 
#include 
using namespace std;/*
* 功能:快排分割函数。每次递归时,将数组中的数据分割为两组,分别比val大的分成一组,比val小的分成一组。
*
* 参数:
*	arr[]: 要分割的数组
*	begin: 数组开始下标
*	end  : 数组的结束位置
*/		
int Partition(int arr[], int begin, int end)
{int val = arr[begin];int i = begin;int j = end;while (i < j){while (i < j && arr[j] > val){j--;}// 如果找到右边的值大于begin,就进行下面的操作,把比val大的放在if (i < j){arr[i] = arr[j];i++;}while (i < j && arr[i] < val){i++;}if (i < j){arr[j] = arr[i];j--;}}arr[i] = val;return i;
}/*
* 功能:求出前topk
*
* 参数:
*	*arr : 求topk的数组
*	begin: 数组开始下标
*	end  : 数组的结束位置
*	k    : 要求解的前topk。
*/
void SelectTopK(int *arr, int begin, int end ,int k)
{int pos = Partition(arr, begin, end);if (pos == k - 1) // 如果上面分割好的pos中间位置,刚好等于topk,直接返回。{				return;}else if (pos > k - 1)  // 假如返回 5  而要找topk=3,则继续快排分割。{SelectTopK(arr, begin, pos - 1, k);}else{SelectTopK(arr, begin, pos - 1, k);}
}
int main()
{int arr[] = { 64,45,52,80,66,68,0,2,18,75 };int size = sizeof arr / sizeof arr[0];// 假如求最小的topK,最后返回数组中的topk个元素。int k = 3;SelectTopK(arr, 0, size - 1,k);for (int i = 0; i < k; i++){cout << arr[i] << " ";}cout << endl;system("pause");return 0;
}

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
进口奶粉的排名 荷兰奶粉十大排... 越来越乱的国内奶粉市场让很多宝妈宝爸都不知道该如何选择奶粉品牌,宝宝的安全是第一位,奶粉的质量以及口...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
不用扬鞭自奋蹄 乘势而上千帆竞... 思明区正全力向“两个进位”目标发起冲刺,努力为建设高素质高颜值现代化国际化的厦门作出“思明贡献”。(...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...