【数据结构】建堆算法复杂度分析及TOP-K问题

【数据结构】建堆算法复杂度分析及TOP-K问题

🔥个人主页大白的编程日记

🔥专栏数据结构


文章目录

  • 【数据结构】建堆算法复杂度分析及TOP-K问题
    • 前言
    • 一.复杂度分析
      • 1.1向下建堆复杂度
      • 1.2向上建堆复杂度
      • 1.3堆排序复杂度
    • 二.TOP-K问题
      • 2.1思路分析
      • 2.2代码实现
    • 后言

前言

哈喽,各位小伙伴大家好!上期我们讲了堆排序和建堆算法。今天我们就来分析一下他们的时间复杂度。话不多说,咱们进入正题。向大厂冲锋!

一.复杂度分析

我们都知道堆是一个完全二叉树。那他的高度h和节点数量N有什么关系呢?

那我们再来对比一下满二叉树和完全二叉树的高度h.

我们用大O渐进表示法看的话他们两个的高度h都可以认为是logN的量级
所以我们的堆的上下调整可以认为是logN,也就是高度次。

因为堆是完全二叉树,而满二叉树也是完全二叉树,所以为了方便证明
我们使用满二叉树来证明(时间复杂度本来看的就是近似值,多几个结点不影响最终结果):

1.1向下建堆复杂度

我们先分别算出第一层到h-1层的节点个数和该层节点的调整次数
然后再推出总的调整次数。

  • 推导

1.2向上建堆复杂度

我们先分别算出第2层到h层的节点个数和该层节点的调整次数
然后再推出总的调整次数。

  • 推导

所以向下建堆的时间复杂度是O(N),向上建堆的复杂度是O(N*logN).
所以以后我们都尽量使用向下调整建堆。因为他的效率更高。

1.3堆排序复杂度

现在我们来看一下我们堆排序的时间复杂度是多少呢?

  • 推导

    堆排序的复杂度是O(N*logN).

二.TOP-K问题

2.1思路分析

我们的堆除了可以用来排序还可以用来解决经典的TOP-K问题。
TOP-K问题:即求数据结合中前K个最大的元素或者最小的元素,一般情况下数据量都比较大。
比如:专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。

  • 方法一
    我们很容易想到直接排序然后取出前K个即可。
    但是这个方法有个致命缺陷。
    如果数据量非常大,排序就不太可取了(可能数据都不能一下子全部加载到内存中)。

    我们发现这个方法在数据量太大的时候并不适用。
    那有什么其他好的方法吗?
  • 方法二
    最佳的方式就是用堆来解决,基本思路如下:
    1 .用数据集合中前K个元素来建堆
    前k个最大的元素,则建K个数的小堆
    前k个最小的元素,则建K个数的大堆
    2 . 用剩余的N-K个元素依次与堆顶元素来比较,
    如果比堆顶元素还要大或小(小堆大 大堆小)则替换堆顶元素,然后向下调整重新建堆。

将剩余N-K个元素依次与堆顶元素比完之后,堆中剩余的K个元素就是所求的前K个最小或者最大的元素。

为什么呢?

  • 证明

    我们通过N-K次比较就可以筛选出N-K个不满足最大前K个数的数
    剩下在堆的数就是最大的前K个。
  • 疑问

我们用反证法可以得知这种情况不存在。

2.2代码实现

  • 生成数据函数
    我们先用srand生成不同的种子防止生成的随机数是伪随机数。
    然后fopen打开文件。循环生成随机数然后写入文件即可。最后关闭文件。
void CreatData()
{int n = 100000;//生成10万个数据srand(time(0));//生成不同的种子FILE* pf = fopen("test.txt", "w");//打开文件for (int i = 0; i < n; i++){int x = rand() % 100001+i;//生成随机数fprintf(pf, "%d\n", x);//写数据}fclose(pf);//关闭文件pf = NULL;
}


这样10万个数据就生成好了。

  • 比较函数

我们先接收k。然后开好k个数是堆空间。
然后从文件读取前k个数并填充到堆里面。然后建堆
然后继续读取文件里的数据直到文件末尾(返回EOF)
然后当数据大于堆顶元素是在进堆,然后重新调整建堆即可。

void test()
{int k;printf("请输入前K个数:");scanf("%d", &k);int* a = (int*)malloc(sizeof(int) * k);//开空间建堆FILE* pf = fopen("test.txt", "r");for (int i = 0; i < k; i++){fscanf(pf, "%d", &a[i]);}//填充数据for (int i = (k - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, k, i);}//建小堆int x;while (fscanf(pf, "%d", &x) !=EOF){if (x > a[0]){a[0] = x;AdjustDown(a, k, 0);}}//对比for (int i = 0; i < k; i++){printf("%d ", a[i]);}//打印
}
  • 检验

那我们如何确保这10个数一定是最大的呢?万一我们的算法写错不是最大的前10个数怎么办?










那我们就可以在不同的地方在一些k标点。
也就是K个很大的数,确保他们是最大的前K个。
然后只需要看结果是不是这k个数即可。

大家发现结果就是我们手动给的这10个数。说明我们的程序时没问题的。

后言

这就是建堆算法复杂度分析及TOP-K问题。这里涉及到许多数学知识。大家可以多看几遍证明图。今天就分享到这里。感谢大佬们垂阅!咱们下期见!拜拜~

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

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

相关文章

深度学习1-简介

人工智能&#xff08;AI&#xff09;旨在打造模仿智能行为的系统。它覆盖了众多方法&#xff0c;涵盖了基于逻辑、搜索和概率推理的技术。机器学习是 AI 的一个分支&#xff0c;它通过对观测数据进行数学模型拟合来学习决策制定。这个领域近年来迅猛发展&#xff0c;现在几乎&a…

前端地位蹭蹭蹭Up!!!

作者&#xff1a;溪饱鱼 链接&#xff1a;juejin.cn/post/7283642910301192244 顺便吆喝一句&#xff0c;如果你本科学历&#xff0c;对技术大厂有向往&#xff0c;对前后端测试岗位有兴趣&#xff0c;不对大厂外包有100%的排斥&#xff0c;可以看看这里&#xff0c;薪酬待遇确…

Ruby语言详解

Ruby语言详解 Ruby&#xff0c;作为一种简单快捷的面向对象脚本语言&#xff0c;自20世纪90年代由日本人松本行弘&#xff08;Yukihiro Matsumoto&#xff09;开发以来&#xff0c;便以其独特的魅力和强大的功能赢得了全球开发者的青睐。Ruby不仅继承了Perl、Smalltalk、Eiffe…

​ ​【Linux】-----工具篇(多模式编辑器vim介绍及配置)

目录 认识常用三种模式 基本操作 Ⅰ、进入/打开vim Ⅱ、模式转换 Ⅲ、退出vim 命令集 Ⅰ、命令模式下 移动光标 删除文字 复制 替换 撤销 批量化注释 批量化去注释 Ⅱ、底行模式下 列出行号 跳转至指定行 查找字符 保存文件 退出vim 查看文件 分屏操作 vim的简…

论文阅读:面向自动驾驶场景的多目标点云检测算法

论文地址:面向自动驾驶场景的多目标点云检测算法 概要 点云在自动驾驶系统中的三维目标检测是关键技术之一。目前主流的基于体素的无锚框检测算法通常采用复杂的二阶段修正模块,虽然在算法性能上有所提升,但往往伴随着较大的延迟。单阶段无锚框点云检测算法简化了检测流程,…

CUE-云原生配置语言

CUE 是一种服务于云化配置的强类型配置语言&#xff0c;由 Go team 成员 Marcel van Lohiuzen 结合 BCL 及多种其他语言研发并开源&#xff0c;可以说是 BCL 思路的开源版实现CUE 是一种服务于云化配置的强类型配置语言&#xff0c;由 Go team 成员 Marcel van Lohiuzen 结合 B…

AI OS

一&#xff0c;概念 AI OS, 或AI for OS&#xff0c;也就是近一年来伴随着人工智能的热度而衍生出的一个新的概念 - 人工智能操作系统。 为什么提出AI OS的概念&#xff1f; 这是因为人工智能技术的发展势头太过迅猛&#xff0c;尤其在深度学习、大模型等AI技术的突破后&…

微信小程序:vant-weapp 组件库、css 变量

vant-weapp 组件库 前往 vant-weapp 官网 npm 使用限制&#xff1a;不支持依赖于 Node.js 内置库、浏览器内置对象、C 插件 的包。 安装 vant-weapp # 通过 npm 安装 npm i vant/weapp -S --production# 通过 yarn 安装 yarn add vant/weapp --production# 安装 0.x 版本 npm i…

Mac环境报错 error: symbol(s) not found for architecture x86_64

Mac 环境Qt Creator报错 error: symbol(s) not found for architecture x86_64 错误信息 "symbol(s) not found for architecture x86_64" 通常是在编译或链接过程中出现的问题。这种错误提示通常涉及到符号未找到或者是因为编译器没有找到适当的库文件或函数定义。 …

powe bi界面认识及矩阵表基本操作 - 1

powe bi界面认识及矩阵表操作 1. 界面认识1.1 选择数据源1.2 选择相关表及点击加载1.3 表字段显示位置1.4 表属性按钮位置1.5 界面布局按钮认识 2. 矩阵表基本操作2.1 选择矩阵表2.2 创建矩阵表2.3 设置字体大小2.4 行填充&#xff1a;修改高度2.5 列宽&#xff1a;设置列的宽度…

【下厨记】青椒土豆丝的做法和写代码之间的关系

在gap year 的尾声&#xff0c;我决定给自己报个厨艺培训班&#xff0c;精进一下厨艺。讲道理&#xff0c;在这样一个充斥着代码的社区写怎么做土豆丝是不是很不搭界&#xff0c;但其实没有&#xff0c;且听我娓娓道来。论&#xff0c;青椒土豆丝做法和写代码之间的关系。 1.找…

git怎么把本地仓库提交到远程仓库

要把本地仓库的内容推送到远程仓库&#xff0c;你需要先设置远程仓库的URL&#xff0c;然后使用git push命令。以下是步骤和示例代码&#xff1a; 1、在本地创建一个新的git仓库或者进入一个已存在的git仓库目录。 2、添加远程仓库&#xff08;如果尚未添加&#xff09;。使用…

使用RedisTemplate操作executePipelined

前言 RedisTemplate 是 Spring 提供的用于操作 Redis 的模板类&#xff0c;它封装了 Redis 的连接、连接池等管理&#xff0c;并提供了一系列的操作方法来简化 Redis 的使用。其中&#xff0c;executePipelined 方法是 RedisTemplate 中的一个高级特性&#xff0c;用于支持 Re…

【Python实战因果推断】55_因果推理概论5

目录 Consistency and Stable Unit Treatment Values Violations Causal Quantities of Interest Consistency and Stable Unit Treatment Values 在上述方程中&#xff0c;隐含着两个基本假设。第一个假设意味着潜在结果与处理是一致的&#xff1a;当时&#xff0c;。换句…

为什么有了MAC还需要IP?

目录 MAC地址&#xff08;Media Access Control Address&#xff09;IP地址&#xff08;Internet Protocol Address&#xff09;为什么需要两者&#xff1f; IP地址和MAC地址在网络通信中扮演着不同的角色&#xff0c;它们各自有独特的功能和用途。下面是它们的主要区别和为什么…

VitePress Config.mts 详细讲解

VitePress 是一个基于 Vite 的静态站点生成器&#xff0c;专为技术文档和博客设计。它继承了 Vite 的快速开发体验&#xff0c;并提供了一套简洁的配置选项。在本文中&#xff0c;我们将深入探讨 VitePress 的 config.mts 配置文件&#xff0c;这是中高级开发者定制站点的关键所…

详解Vue中nextTick的原理与作用

Vue中的nextTick是一个非常重要的API&#xff0c;它允许开发者延迟回调函数的执行直到下次DOM更新循环之后。这一机制在Vue开发中非常有用&#xff0c;特别是在处理DOM更新和异步操作时。下面将详细解释nextTick的原理与作用。 原理 Vue的DOM更新是异步进行的。当数据发生变化…

Vue3相比于Vue2进行了哪些更新

1、响应式原理 vue2 vue2中采用 defineProperty 来劫持整个对象&#xff0c;然后进行深度遍历所有属性&#xff0c;给每个属性添加getter和setter&#xff0c;结合发布订阅模式实现响应式。 存在的问题&#xff1a; 检测不到对象属性的添加和删除数组API方法无法监听到需要对…

Shader笔记1:基础概念

有相当一部分来自shader圣经 Base of CG Concepts Tangent, Normal and Binormal N&#xff1a;法线&#xff08;Normal, N&#xff09;垂直于表面 T&#xff1a;切线&#xff08;Tangent, T&#xff09;与U方向同向 B&#xff1a;副切线&#xff08;BiTangent, B&#xff09…

ADS 使用教程(十六)Using Sliders for Data Processing

上一篇&#xff1a;ADS 使用教程&#xff08;十五&#xff09;Multi-Dimensional Data Processing in ADS 在这一节&#xff0c;我们来谈论一下如何在进行多维数据处理时使用滑块&#xff08;Sliders&#xff09;来进行数据处理和分析。通过该方法&#xff0c;我们可以通过拖动…