堆、堆排序、堆应用

news2024/11/27 22:34:24

一、概述

“堆”(Heap),原地排序、时间复杂度O(nlogn)的排序算法。

  • 堆是一个完全二叉树;
  • 堆中每一个节点的值都必须大于等于(或者小于等于)其子树中每个节点的值;

二、如何实现一个堆

使用数组来存储
数组中下标为 i 的节点的左子节点,就是下标为 i∗2 的节点,右子节点就是下标为 i∗2+1 的节点,父节点就是下标为 2i​ 的节点。
在这里插入图片描述
往堆中插入一个数据(堆化)

  • 从下往上堆化
    在这里插入图片描述

  • 从上往下堆化

删除堆顶元素
可以选择删除堆顶元素后,将堆中的最后一个元素放到堆顶,然后进行从上往下堆化。包含n个节点的完全二叉树,树的高度不会查过log2​n,所以堆化的时间复杂度和树的高度成正比,也就是O(logn)。
在这里插入图片描述

三、如何基于堆实现排序

1、建堆

  1. 起始堆中只有一个元素,下标为1的数据,然后根据前面的插入操作,将2到下标n的数据依次插入到堆中;
  2. 从后往前处理数据,叶子节点往下堆化只能自己跟自己比较,所以从最后一个非叶子节点开始,依次堆化;
    在这里插入图片描述
    在这里插入图片描述

private static void buildHeap(int[] a, int n) {
  for (int i = n/2; i >= 1; --i) {
    heapify(a, n, i);
  }
}

private static void heapify(int[] a, int n, int i) {
  while (true) {
    int maxPos = i;
    if (i*2 <= n && a[i] < a[i*2]) maxPos = i*2;
    if (i*2+1 <= n && a[maxPos] < a[i*2+1]) maxPos = i*2+1;
    if (maxPos == i) break;
    swap(a, i, maxPos);
    i = maxPos;
  }
}

那么建堆时间复杂度是多少?
O(n)。

2、排序
堆化为大顶堆后,数据已经按照顺序存放了,所以将堆顶数据取出,然后将最后一个元素放入堆顶进行堆化,依次进行。
在这里插入图片描述

// n表示数据的个数,数组a中的数据从下标1到n的位置。
public static void sort(int[] a, int n) {
  buildHeap(a, n);
  int k = n;
  while (k > 1) {
    swap(a, 1, k);
    --k;
    heapify(a, k, 1);
  }
}

时间复杂度:建堆O(n),排序O(nlogn),因此整体时间复杂度是O(nlogn)。

四、堆排序和快速排序对比

  • 快速排序,数据是顺序访问。而对于堆排序,数据跳着访问,这样对于CPU缓存不友好。
  • 同样的数据,排序中,堆排序的数据交换次数多于快速排序。

五、堆排序的应用

1、优先级队列

  • 合并有序小文件:100个小文件,每个文件大小100MB,每个文件里都是有序的字符串,希望将这100个文件合并成一个有序的大文件。操作类似于归并排序,从100个文件中,各取一个字符串,放入数组中,然后比较大小,再把最小的字符串放入合并后的大文件,并从数组中删除。另外可以组建小顶堆,每次取堆顶元素放入合并的大文件,在从小文件中取下一个字符串放入堆中,依次玄幻操作。
  • 高性能服务器:定时器中维护很多定时任务,每个任务都有一个出发执行的时间点,定时器需要固定时间(1S),扫描一遍任务列表,查看是否有任务到达执行时间。如果把任务列表按照还需要等待时间的长短设计为一个小顶堆,那么定时器只需要到点0去看看堆顶的任务有没有到达执行时间就可,然后计算新的堆顶任务剩余的时间T,然后等待T秒再来取任务。

2、利用堆求Top K
针对静态数据集合,组件一个大小为K的大顶堆,依次从数组中取元素和堆顶元素进行比较,遍历完数组后,堆中的元素就是Top k数据了。遍历数组时间复杂度时O(n),每次堆化需要O(logK)的时间复杂度,所以整体最坏情况下,n个元素都入堆依次,总的时间复杂度就是O(nlogK)。

3、利用堆求中位数
对于静态数据,中位数是固定的,可以先排序,第n/2个数据就是中位数。每次询问中位数时可以直接返回,当时如果是动态数据集合时,中位数不停的变动,每次询问都需要排序。
可以借助堆,维护一个大顶堆存前n/2或n/2+1个数据,再维护一个小顶堆,存后n/2个数据。新加入一个数据时,如果数据小于大顶堆中的元素,将数据插入大顶堆;否则,将数据插入到小顶堆。如果插入后两个堆中的数据不满足前面的约定,从一个堆中取出元素移动到另一个堆中。
在这里插入图片描述
如何求接口的99%相应时间?
将上面的大小堆个数比按照99:1设计。

4、如何获取Top 10最热门的搜索关键词
假设现在有一个包含 10 亿个搜索关键词的日志文件,如何能快速获取到热门榜 Top 10 的搜索关键词呢?
单机环境,内存1GB。
首先统计每个关键词出现的频率,使用散列表、平衡二叉树或者其他支持快速查找、插入的数据结构记录关键词及其出现的次数。
顺序扫描10亿个关键词,扫描到后在散列表中查找,有的话次数+1,没有的话插入,以此类推。然后构建Top K的小顶堆,遍历散列表,依次与堆顶元素进行对比。遍历完散列表后,堆中的元素就是Top K频率的关键词。
如果10亿中的关键词很多,假如说有1亿条,每个关键词平均长度50字节,那么存储就需要5GB的内存空间,那么散列表为了避免频繁冲突。所以需要的内存空间大。1GB可能不够用。因此所以需要创建10个空文件00、01、02…,09,遍历10亿个关键字,按照哈希算法将结果取10的模,得到结果就是此关键词被分到的文件编号。然后利用散列表和堆,分别求出每个文件的Top 10,然后将每个文件的Top 10放在一块100个关键词求其Top 10就可。

5、求每间隔1小时新闻网站点击Top 10的新闻
有一个访问量非常大的新闻网站,希望将点击量排名 Top 10 的新闻摘要,滚动显示在网站首页 banner 上,并且每隔 1 小时更新一次。如何来实现呢?
根据新闻个数构建散列表,每点击一次更新其点击量;
每隔一个小时遍历散列表维护一个大小为10的小顶堆;

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

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

相关文章

第2-4-7章 docker安装WorkBench-规则引擎Drools-业务规则管理系统-组件化-中台

文章目录8. WorkBench8.1 WorkBench简介8.2 安装方式8.2.1 传统方式安装8.2.2 docker安装drools workbench8.3 使用方式8.3.1 创建空间、项目8.3.2 创建数据对象8.3.3 创建DRL规则文件8.3.4 创建测试场景8.3.5 设置KieBase和KieSession8.3.6 编译、构建、部署8.3.7 在项目中使用…

Intel PAUSE 指令变化如何影响 MySQL 的性能

导读 x86、arm指令都很多&#xff0c;无论是应用程序员还是数据库内核研发大多时候都不需要对这些指令深入理解&#xff0c;但是 Pause 指令和数据库操作太紧密了&#xff0c;本文通过一次非常有趣的性能优化来引入对 Pause 指令的理解&#xff0c;期望可以事半功倍地搞清楚 C…

微服务线上问题排查困难?不知道问题出在哪一环?那是你还不会分布式链路追踪

咱们以前单体应用里面有很多的应用和功能&#xff0c;依赖各个功能之间相互调用&#xff0c;使用公共的代码包等等&#xff0c;排查问题&#xff0c;使用类似于 gdb/dlv 工具或者直接查看代码日志&#xff0c;进行定位和分析 但是现在我们基本上都是微服务架构了&#xff0c;将…

Node.js 入门教程 20 查看 npm 包安装的版本 21 安装 npm 包的旧版本

Node.js 入门教程 Node.js官方入门教程 Node.js中文网 本文仅用于学习记录&#xff0c;不存在任何商业用途&#xff0c;如侵删 文章目录Node.js 入门教程20 查看 npm 包安装的版本21 安装 npm 包的旧版本20 查看 npm 包安装的版本 若要查看所有已安装的 npm 软件包&#xff08…

JetpackCompose Navigation导航快速上手

Navigation 快速上手 下面案例简要展示使用 Compose 版本的 Navigation 库来实现两个页面之间的跳转 这是完整的结构&#xff08;忽略掉红线划过的那个包&#xff09; 编写欲跳转的两个页面 编写 Demo1 页面 子页面使用多个 composable 组件相组合的方法一一装配起来 Demo1m…

【博客543】golang pprof性能调试:寻找cpu瓶颈

golang pprof性能调试&#xff1a;寻找cpu瓶颈 1、引入pprof进行性能调试 在代码中加入&#xff1a; import _ "net/http/pprof"go func() {http.ListenAndServe("0.0.0.0:8899", nil) }()示例&#xff1a;为冒泡排序加入pprof debug package mainimpo…

月薪2万的大数据职位,为什么必须学习Python?

前言 马云说&#xff1a;“未来最大的资源就是数据&#xff0c;不参与大数据十年后一定会后悔。”毕竟出自wuli马大大之口&#xff0c;今年二月份我开始了学习大数据的道路&#xff0c;直到现在对大数据的学习脉络和方法也渐渐清晰。 我们先来看一下数据分析相关职位现在的薪…

Cys(Npys)-(Arg)₉,H2N-C(Npys)-RRRRRRRRR-OH

可渗透细胞的非精氨酸酰胺&#xff0c;可以很容易地偶联到负载分子上&#xff0c;例如通过马来酰亚胺-硫醇偶联。 编号: 126721中文名称: Cys(Npys)-(Arg)₉英文名: Cys(Npys)-(Arg)₉单字母: H2N-C(Npys)-RRRRRRRRR-OH三字母: H2N-Cys(Npys)-Arg-Arg-Arg-Arg-Arg-Arg-Arg-Arg-…

多肽标签TC tag,H2N-CCPGCC-OH

编号: 168488中文名称: 多肽标签TC tag英文名: TC tag单字母: H2N-CCPGCC-OH三字母: H2N-Cys-Cys-Pro-Gly-Cys-Cys-COOH氨基酸个数: 6分子式: C19H32N6O7S4平均分子量: 584.75精确分子量: 584.12等电点(PI): 9.13pH7.0时的净电荷数: 3.85平均亲水性: -1疏水性值: 1.33来源: 人工…

Vision Transformer

Vision Transformer 将Transformer应用于CV领域。 不了解Transformer的先去看下&#xff1a;一文看懂Transformer 对比Transformer&#xff0c;ViT的特殊之处不多。因为作者说了他们想要做“尽量少的改动”将Transformer直接应用于图像领域 论文下载地址&#xff1a;https:…

留学Paper写作需要怎么正确引用?

1.MLA文献引用格式的基本描述&#xff1a;文学类Paper通常使用MLA&#xff08;Modern Language Association&#xff09;格式。作者在正文中用括号夹注的形式注明参考文献的简要出处&#xff0c;即&#xff08;作者姓氏页码&#xff09;。 Ancient writers attributed the inve…

小学生python游戏编程arcade----坦克换色

小学生python游戏编程arcade----坦克换色前言坦克换色1、RGB颜色1.1 RGB1.2 PIL 模块中的image1.3 效果图![在这里插入图片描述](https://img-blog.csdnimg.cn/f533a0bed98f4b49a462a2f056c35786.png)#### 1.4 代码实现1.5 总结2、RGB转换为HSV2.1 RGB2.2 HSV2.3 python RGB 转…

《前端框架开发技术》HTML+CSS+JavaScript 制作个人简历模板

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

23、Mybatis查询功能4(查询结果为一个map集合(多条数据))

Mybatis查询功能4&#xff08;查询结果为一个map集合&#xff08;多条数据&#xff09;&#xff09; 可以用Lsit集合接收可以用MapKey注解设置键&#xff08;用一个唯一标识&#xff09;第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a;

我的第一个Servlet程序,并理解浏览器和代码如何关联在一起

目录 Servlet 第一个Servlet程序 1.创建项目 maven是什么 如何创建maven项目 2.引入Servlet依赖 找到库中maven代码 3.创建目录结构 4.编写代码 理解注解Webserlet 5.打包程序 生成war包 6.部署程序 7.验证程序 二.理解浏览器发的请求是怎么和自己写的代码建立联…

景联文智能标注平台将数据处理效率提升十倍以上!数据精准度最高可达99%

目前主流的机器学习方式是以有监督的深度学习方式为主&#xff0c;这对标注数据有着强较依赖性需求&#xff0c;未经标注处理过的原始数据多以非结构化数据为主&#xff0c;这些数据难以被机器识别和学习。这就需要标注员借助数据标注工具对数据进行标注。 使用高效率的标注工具…

如何知道你的Linux内核占用的内存大小?

如何知道你的Linux内核占用的内存大小&#xff1f;1、代码段等2、kernel heap2.1、kmalloc2.2、vmalloc3、进程的页表4、内核占用内存大小总和1、代码段等 内核所需的代码段、bss段&#xff0c;内核栈等。 / # dmesg | grep Memory Memory policy: Data cache writealloc M…

springboot使用mybatis

springboot使用mybatis 本文目录springboot使用mybatis引入maven依赖新增数据库配置创建数据库表实体类编写mapper接口层通过xml文件mapper中直接使用注解编写mapper.xmlIDEA创建mybatis的xml文件parameterType启动类controller调用引入maven依赖 <dependency><groupI…

视频转音频怎么转?来试试这三个方法

如今我们可以看到有一些人会把电影/电视变成听电影/电视&#xff0c;相信大家都会感觉很不可思议吧&#xff01;电影/电视不是用来看的吗&#xff1f;听就没办法享受到那种视觉上的震撼了&#xff0c;其实不然&#xff0c;听电影/电视也是一种别样的享受&#xff0c;特别是对有…

看完这篇还不懂MySQL的MVCC机制算我输

前言 MySQL中大名鼎鼎的MVCC机制想必大家都有所耳闻吧&#xff0c;虽然在平时MySQL使用过程中基本上用不到&#xff0c;但是面试中出场率十分高&#xff0c;而且作为架构师的你也是需要知道它的工作机制。那么你对MVCC机制了解多少呢&#xff1f;MVCC机制是用来干嘛的呢&#…