数据结构与算法_大数据处理_求topK的两种求解方法

news2025/7/12 11:36:02

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

1 大/小根堆法

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

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

代码

#include <iostream>
#include <vector>
#include <time.h>
#include <queue>
#include <functional>
using namespace std;

int main()
{
	vector<int> 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<int> 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<int, vector<int>, greater<int>> 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 <iostream>
#include <functional>
#include <time.h>
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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/5625.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python 算法:学习二分法

二分法&#xff0c;一个看似简单&#xff0c;逻辑易懂的算法&#xff0c;但是初次接触可能会有很多坑&#xff01;主要是边界处理的问题。 下面以一个耳熟能详的案例来展开&#xff1a; 案例描述&#xff1a; 小B从1~100之间&#xff08;含边界值&#xff09;任意想一个数字&a…

Spring Security 在登录时如何添加图形验证码

前言 在前面的几篇文章中&#xff0c;登录时都是使用用户名 密码进行登录的&#xff0c;但是在实际项目当中&#xff0c;登录时&#xff0c;还需要输入图形验证码。那如何在 Spring Security 现有的认证体系中&#xff0c;加入自己的认证逻辑呢&#xff1f;这就是本文的内容&…

matplotlib简介

matplotlib是一款用于画图的软件&#xff0c;以下步骤建议在.ipynb中完成。 导包 你需要导入以下包&#xff1a; import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np一个简单案例 matplotlib 在 Figure上绘制图形&#xff0c;每一个Figure会包含…

【附源码】Python计算机毕业设计手游账号交易系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Java注解式开发

目录 1. ssm框架的搭建 1.1 maven项目的创建 1.2 导入所需的包到pom.xml文件中 1.3 导入数据库连接文件、日志文件、redis连接文件 1.3.1 数据库连接文件 1.3.2 日志文件 1.3.3 redis连接文件 1.4 导入spring-mybatis、spring-mvc、spring-base、spring-redis四种集成文…

改变自己 只需要两年

改变自己 只需要两年 https://v.douyin.com/rLDmdQK/ 可以快速浏览上面视频 今天分享的这篇文章是TED上的一篇演讲 希望对下定决心想改变的你一些帮助。 用两年时间证明你可以 两年时间不算多长&#xff0c;但与此同时&#xff0c;很多事情都能在两年内完成&#xff0c;你…

WinHex(三)

目录 一、新建简单卷 二、MBR作用与结构 一、新建简单卷 1.右键点击刚刚新建的虚拟磁盘&#xff0c;选择新建简单卷。我新建了两个一个是NTFS&#xff0c;一个是FAT32 2.我们在刚刚新建的虚拟磁盘中放入一张图片&#xff0c;打开WinHex,点击“打开磁盘”选项&#xff0c;打…

[野火]STM32 F103 HAL库开发实战指南笔记之简单外设总结

1、GPIO编程总结 使能 GPIO 端口时钟&#xff1b;初始化 GPIO 目标引脚为推挽输出模式&#xff1b;编写简单测试程序&#xff0c;控制 GPIO 引脚输出高、低电平。 这部分宏控制 LED 亮灭的操作是直接向 BSRR 寄存器写入控制指令来实现的&#xff0c;对 BSRR 低 16 位 写 1 输出…

大学生静态HTML网页源码 我的校园网页设计成品 学校班级网页制作模板 web课程设计 dreamweaver网页作业

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

从0实现线性回归

编码题&#xff1a; 按要求完成下面的内容 1请用python完成从0实现线性回归&#xff0c;尝试使用不同的训练参数&#xff08;学习率&#xff0c;迭代次数&#xff09;&#xff0c; 以及不同的评价方法&#xff08;MSE,MAE,RMSE,R2&#xff09;等。 2比较说明sklearn的线性模…

断言(assert)的用法

参考&#xff1a;https://www.runoob.com/w3cnote/c-assert.html 目录作用总结与注意事项Demo作用 assert 是个宏&#xff0c;并且作用并非"报错"。 assert() 的用法像是一种"契约式编程"&#xff0c;程序满足我的假设条件&#xff0c;才能正常良好的运作…

做视频素材资源(free视频,音频,图片)

素材资源 一、视频 Videezy &#xff1a;https://www.videezy.com/ Videovo&#xff1a;https://www.videvo.net/ mixkit&#xff1a;https://mixkit.co/&#xff0c;可以 distill&#xff1a;https://wedistill.io/ splitshire&#xff1a;https://www.splitshire.com/ pixa…

Mysql常见指令以及用法(保姆级)

文章目录基础篇通用语法及分类DDL&#xff08;数据定义语言&#xff09;数据库操作注意事项表操作DML&#xff08;数据操作语言&#xff09;添加数据注意事项更新和删除数据DQL&#xff08;数据查询语言&#xff09;基础查询条件查询聚合查询&#xff08;聚合函数&#xff09;分…

前端性能-首次加载优化70%

前言 本篇文章&#xff0c;我们来总结归纳下万恶的this以及衍生出来的call/apply/bind对this进行绑定&#xff0c;想了很久&#xff0c;决定用实例演示的方式来讲解this&#xff0c;这样才能够理解this&#xff0c;因为this确实变化莫测&#xff0c;只靠概念&#xff0c;是不能…

【JS 构造|原型|原型链|继承(圣杯模式)|ES6类语法】下篇

⌚️⌚️⌚️个人格言&#xff1a;时间是亳不留情的&#xff0c;它真使人在自己制造的镜子里照见自己的真相! &#x1f4d6;Git专栏&#xff1a;&#x1f4d1;Git篇&#x1f525;&#x1f525;&#x1f525; &#x1f4d6;JavaScript专栏&#xff1a;&#x1f4d1;js实用技巧篇…

【数据结构】带头双向循环链表基本操作的实现(C语言)

&#x1f680; 作者简介&#xff1a;一名在后端领域学习&#xff0c;并渴望能够学有所成的追梦人。 &#x1f40c; 个人主页&#xff1a;蜗牛牛啊 &#x1f525; 系列专栏&#xff1a;&#x1f6f9;初出茅庐C语言、&#x1f6f4;数据结构 &#x1f4d5; 学习格言&#xff1a;博…

峰会实录 | StarRocks PMC Chair 赵纯:数据分析的极速统一3.0 时代

作者&#xff1a;StarRocks PMC Chair 赵纯&#xff08;本文为作者在 StarRocks Summit Asia 2022 上的分享&#xff09; 一年前&#xff0c;StarRocks 源码开放&#xff0c;StarRocks 社区也正式成立。经过一年发展&#xff0c;社区已经获得了 3400 个 Star&#xff0c;7500 …

如何用windows上架ios到苹果商城

1.苹果账号 1.你需要申请苹果账号 官网有提示&#xff1a;Sign In - Apple 2.登录 登录后店家 account&#xff0c;进入account。 点击证书&#xff0c;进入。 2.开始上架步骤 1.注册标识符&#xff08;Bundle ID&#xff09; 进入这个界面后&#xff0c;点击 Identifiers …

Elasticsearch快照备份

目录 1、Repositories 1、配置路径 2、注册快照存储库 2、查看注册的库 3、创建快照 1、为全部索引创建快照 2、为指定索引创建快照 4、查看备份完成的列表 5、删除快照 6、从快照恢复 1、恢复指定索引 2、恢复所有索引&#xff08;除.开头的系统索引&#xff09; …

【Redis】 数据结构:Redis对象与编码(底层结构)对应关系详解

【Redis】 数据结构&#xff1a;Redis对象与编码(底层结构)对应关系详解 文章目录【Redis】 数据结构&#xff1a;Redis对象与编码(底层结构)对应关系详解Redis对象与编码(底层结构)对应关系引入Redis数据结构-RedisObjectredisObject数据结构Redis的编码方式五种数据结构Redis…