最大堆、最小堆Java实现,解决TOP K问题

本文介绍了最大堆和最小堆的概念,包括它们在完全二叉树中的定义,以及TOP K问题的解释。通过最小堆解决TOP K问题,避免了全量排序,提高了效率。文章详细讲解了最小堆的构建、删除操作,并展示了如何利用最小堆在Java中实现解决TOP K问题的方法。
摘要由CSDN通过智能技术生成

一、基础知识

1.1 什么是最大(小)堆

最大堆,最小堆类似,以下以最小堆为例进行讲解。
最小堆是满足以下条件的数据结构:

  1. 它是一棵完全二叉树
  2. 所有父节点的值小于或等于两个子节点的值

1.2 什么是完全二叉树

除了最后一层之外的其他每一层都被完全填充,并且所有结点都保持向左对齐。

1.3 什么是TOP K问题

Top K指的是从n(很大)个数据中,选取最大(小)的k个数据。例如学校要从全校学生中找到成绩最高的500名学生,再例如某搜索引擎要统计每天的100条搜索次数最多的关键词。

二、堆排序解决TOP K

对于TOPK问题,解决方法有很多:

方法一:对源数据中所有数据进行排序,取出前K个数据,就是TopK。

但是当数据量很大时,只需要k个最大的数,整体排序很耗时,效率不高。

方法二:维护一个K长度的数组a[],先读取源数据中的前K个放入数组,对该数组进行升序排序,再依次读取源数据第K个以后的数据,和数组中最小的元素(a[0])比较,如果小于a[0]直接pass,大于的话,就丢弃最小的元素a[0],利用二分法找到其位置,然后该位置前的数组元素整体向前移位,直到源数据读取结束。

这比方法一效率会有很大的提高,但是当K的值较大的时候,长度为K的数据整体移位,也是非常耗时的。

对于这种问题,效率比较高的解决方法是使用最小堆。

2.1 最小堆思路

最小堆(小根堆)是一种数据结构,它首先是一棵完全二叉树,并且,它所有父节点的值小于或等于两个子节点的值。

最小堆的存储结构(物理结构)实际上是一个数组。如下图:
在这里插入图片描述
堆有几个重要操作:

BuildHeap:将普通数组转换成堆,转换完成后,数组就符合堆的特性:所有父节点的值小于或等于两个子节点的值。

Heapify(int i):当元素i的左右子树都是小根堆时,通过Heapify让i元素下降到适当的位置,以符合堆的性质。

回到上面的取TopK问题上,用最小堆的解决方法就是:先去源数据中的K个元素放到一个长度为K的数组中去,再把数组转换成最小堆。再依次取源数据中的K个之后的数据和堆的根节点(数组的第一个元素)比较,根据最小堆的性质,根节点一定是堆中最小的元素,如果小于它,则直接pass,大于的话,就替换掉跟元素,并对根元素进行Heapify,直到源数据遍历结束。

2.2 最小堆解决TOPK

最小堆的实现:

public class MinHeap
{
   
	// 堆的存储结构 - 数组
	private int[] data;
	
	// 将一个数组传入构造方法,并转换成一个小根堆
	public MinHeap(int[] data)
	{
   
		this.data = data;
		buildHeap();
	}
	
	// 将数组转换成最小堆
	private void buildHeap()
	{
   
		// 完全二叉树只有数组下标小于或等于 (data.length) / 2 - 1 的元素有孩子结点,遍历这些结点。
		// *比如上面的图中,数组有10个元素, (data.length) / 2 - 1的值为4,a[4]有孩子结点,但a[5]没有*
        for (int i = (data.length
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值