堆在实际开发中的使用有哪些?

简介: 堆在实际开发中的使用有哪些?

堆在实际开发中的使用有哪些?

优先级队列

队列的最大特性是先进先出,在优先级队列中,数据的出队顺序是按照优先级来的,优先级最高的最先出队。

优先级队列和堆很像,往优先级队列中插入一个元素,就相当于在堆中插入一个元素,从优先级队列中取出优先级最高的元素,就和取出堆顶元素一样。

合并有序小文件

假设有 100 个小文件,每个文件的大小是 100MB,每个文件中存储的都是有序的字符串。现在将这些100个小文件合并成一个有序的大文件。

第一种方法,我们可以从这一百个文件中,各取出第一个字符串,放入数组中,然后比较大小,把最小的那个字符放入合并后的大文件中,然后从数组中删除。

然后我们再从删除的的那个字符串所在的文件中,取出下一个字符串,重复上述操作,直到所有文件都合并完成。

这里每次都要比较所有的文件,然后找出最小值,每轮的比较遍历数组中所有的数据,时间复杂度差不多为O(n)

如果我们从小文件中取出的字符串放入小顶堆中,堆顶元素也就是优先级队列队首的元素,就是最小的字符串。我们把字符串放入大文件中,并从堆中删除。然后再从小文件中取出下一个字符串,放入堆中。循环这个过程,直到所有文件都合并完成。

我们每次只需要取出堆顶元素即可,这时候的操作就是删除堆顶元素和插入新的元素,而他们的时间复杂度都是O(logn)

高性能定时器

以前做定时任务,很多时候可能要每隔一段时间去扫描一遍任务,查看是否有任务要执行,只有何种做法很低效。

第一,任务的约定执行时间离当前时间可能还有很久,这样前面很多次扫描其实都是徒劳的;

第二,每次都要扫描整个任务列表,如果任务列表很大的话,会比较耗时。

可以使用优先级队列解决问题,按照任务设定的执行时间,将这些任务存储在优先级队列中,队列首部存储的是最先执行的任务。

我们用队首任务的执行时间点,与当前时间点相减,得到一个时间间隔 T,即当前时间开始,需要等待多久,才会有第一个任务需要执行,这样定时器就可以设定在 T 秒后,再来执行任务,这期间不需要做任何事情。

求 Top K 的数据

求数据中前 K 大的数据

我们首先创建一个容纳 K 个数据的小顶堆,堆顶数据是最小的那个,然后每新增一个数据,与堆顶元素进行比较,如果比堆顶元素小,则舍弃掉,如果比堆顶元素大,则删除堆顶元素,把这个元素插入到小顶堆中。重复上述操作,直到所有数据都比较完,堆中存放的数据一直是需要的数据。

创建堆的时候,堆化的时间复杂度为O(logn),堆的删除和添加元素的时间复杂度都是 O(logn),假设数组中的所有元素都要进行添加操作,那么整个操作的时间复杂度就是O(nlogn)

求中位数

求一组动态数据集合的中位数

假设有 n 个数字,如果我们把一组数字按照从小到大的顺序排好序,如果 n 是偶数,那么中位数就是第 n/2n/2+1个数据,我们可以从中选取一个。如果 n 是奇数,那么中位数就是第 n/2+1个数据。

  1. 数据按照从小到大的顺序排列
  2. 创建两个堆,一个大顶堆和一个小顶堆,假如有偶数个数据,在大顶堆中存放前 n/2个数据,如果有奇数个数据,就在大顶堆中存放前n/2+1个数据,
  3. 其余数据在小顶堆中存放,这时候大顶堆的堆顶数据就是中位数。
  4. 如果有新增数据,就与两个堆的堆顶数据进行对比,如果大于等于小顶堆的堆顶元素,就存放到小顶堆中,如果小于等于大顶堆的堆顶元素,就存放到大顶堆中。
  5. 此时很容易出现数量不匹配的情况, 不再满足第二步的条件,此时,我们只要数量多的一方的堆顶数据移动到数量少的一方即可。
  6. 然后调整堆中数据的大小关系,即可保持平衡。

堆化的时间复杂度为O(logn),中位数的获取时间复杂度为O(1)

同样的道理我们还可以求解任意比例的数据,比如快速求解接口的99%响应时间。

目录
相关文章
|
6月前
|
存储 Java
用java实现堆
用java实现堆
53 5
|
算法 Java
【面试题精讲】JVM-详细说说引用计数法的缺点-循环依赖
【面试题精讲】JVM-详细说说引用计数法的缺点-循环依赖
|
4月前
|
存储 算法 Java
Java面试题:解释JVM的内存结构,并描述堆、栈、方法区在内存结构中的角色和作用,Java中的多线程是如何实现的,Java垃圾回收机制的基本原理,并讨论常见的垃圾回收算法
Java面试题:解释JVM的内存结构,并描述堆、栈、方法区在内存结构中的角色和作用,Java中的多线程是如何实现的,Java垃圾回收机制的基本原理,并讨论常见的垃圾回收算法
63 0
|
6月前
|
存储 算法
堆的知识点总结
堆的知识点总结
49 1
|
6月前
|
存储 算法 安全
堆的应用例子
【5月更文挑战第6天】堆栈是一种LIFO(后进先出)数据结构,支持push、pop、isEmpty、isFull和peek等操作。内部使用切片存储接口类型的元素
66 0
堆的应用例子
|
6月前
|
存储 C++
C++ 栈和堆的作用机制,及特点区别
在介绍C++中的十分重要的动态内存管理机制之前,有必要先单独来介绍一下C++中的两个概念,分别是栈和堆。
68 2
|
6月前
|
存储 缓存 监控
JVM工作原理与实战(二十四):堆的垃圾回收-对象引用
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了强引用、软引用、弱引用、虚引用、终结器引用等内容。
76 0
|
存储
【数据结构】优先级队列(堆)重点知识汇总(附有代码)
【数据结构】优先级队列(堆)重点知识汇总(附有代码)
118 0
【数据结构】堆/堆排序(含top-k问题)(调整方式)(简洁,含代码)
【数据结构】堆/堆排序(含top-k问题)(调整方式)(简洁,含代码)
【数据结构——堆】堆的基本功能和堆排序
一、堆的定义 堆的本质是一个数组,但是这个数组被看作成一棵完全二叉树。 堆分为两种,大根堆和小根堆 1.大根堆 大根堆是每一个节点的值都大于它左右孩子节点的值。 如下图所示,这就是一个大根堆:每个父亲都大于它的孩子。