算法——TOP K问题最小堆实现
来源:互联网 发布:非负矩阵分解 matlab 编辑:程序博客网 时间:2024/06/05 12:41
1. 问题背景
在实际应用中,我们经常会遇到在一大推数据中找出最大的几个数的问题,也就是我们提到的TOP K问题。K表示需要找出数据的数量
2. 解决方案
TOP K问题也有多种解决方案,比如排序,最后截取靠前或者靠后的K个数据。当数据量小的时候,排序解决起来当然可以,算法简单,排序算法也有很多现成的。当数据量很大时,维护一个很长的数组,不管是空间存储上还是排序耗费的时间上都可能难以接受。这时我们可以采用最小堆的方式来实现,只需要维护一个K长度的数组就行
3. 具体实现
数据结构最小堆MinHeap, 其中最重要的是堆的调整adjustHeap
package org.cyxl.common;/** * Created by jeff on 16/5/11. */public class MinHeap { // 堆的存储结构 - 数组 private int[] data; /** * 初始化堆中的数据,以int的最小值作为初始值 * * @param k */ public MinHeap(int k) { this.data = new int[k]; for(int i=0;i<k;i++){ data[i]=Integer.MIN_VALUE; } } private void adjustHeap(int i) { //获取左右结点的数组下标 int l = left(i); int r = right(i); // 这是一个临时变量,表示 跟结点、左结点、右结点中最小的值的结点的下标 int min = i; // 存在左结点,且左结点的值小于根结点的值 if (l < data.length && data[l]<data[i]){ min = l; } // 存在右结点,且右结点的值小于以上比较的较小值 if (r < data.length && data[r]<data[min]){ min = r; } // 左右结点的值都大于根节点,直接return,不做任何操作 if (i == min) return; // 交换根节点和左右结点中最小的那个值,把根节点的值替换下去 swap(i, min); // 由于替换后左右子树会被影响,所以要对受影响的子树再进行adjustHeap adjustHeap(min); } /** * 获取右结点的数组下标 * @param i * @return */ private int right(int i) { return (i + 1) << 1; } /** * 获取左结点的数组下标 * @param i * @return */ private int left(int i) { return ((i + 1) << 1) - 1; } /** * 交换元素位置 * * @param i * @param j */ private void swap(int i, int j) { int tmp = data[i]; data[i] = data[j]; data[j] = tmp; } /** * 将数值加入到堆中 * * @param element */ public void add(int element) { if(element>data[0]) { data[0] = element; adjustHeap(0); } } public int[] getData(){ return data; } @Override public String toString(){ StringBuilder builder = new StringBuilder(); builder.append("{"); for (int i=0;i<data.length;i++){ builder.append(data[i]); if(i!=data.length-1){ builder.append(","); } } builder.append("}"); return builder.toString(); }}
4. 测试
public static void main(String[] args){ int[] a = {12,1,5425,12,43,734,343,999,8,99,55,2,222,444,11}; //求最大的10个 int k=10; MinHeap heap = new MinHeap(k); for(int i:a){ heap.add(i); } System.out.print(heap); }
输出结果是
{12,43,55,99,222,343,999,734,5425,444}
5. 扩展
5.1 当然实际应用中,我们找的可能不是单纯的数字。更可能是和这些数字相关的某些对象。比如找出年龄最大的10个用户,这时我们的User对象可以实现Comparable接口来实现比较。
5.2 这里我们是最小堆来实现TOP K问题,当然也可以用最大堆来找出最小的K个值
5.3 对于最小(大)堆的定义以及特点可以网上查看一下
0 0
- 算法——TOP K问题最小堆实现
- 算法——TOP K问题最小堆实现扩展
- 最小堆算法求Top K
- 最小堆JAVA(Top K问题)
- Top K问题——基于堆排序
- 使用堆实现Top K 算法 JS 实现
- 转 -- Top K算法问题的实现
- Top K算法问题的实现
- Top K算法问题的实现
- 【算法总结-top K】堆--查找最小(大)的k个元素
- 【算法总结-top K】堆--查找最小(大)的k个元素
- TOP K算法问题
- TOP-K问题-堆排序和快排实现
- 【算法——Python实现】最大堆和最小堆
- 算法理解——top K问题实例
- 关于数组TOP K算法(快排及最小堆方式C代码)
- 关于数组TOP K算法(快排及最小堆方式C代码)
- 算法导论最小堆实现k路归并
- Quartz中时间表达式的设置-----corn表达式
- linux “源代码包”和“二进制包”的区别
- 【笔记】 《js权威指南》- 第19章 JQuery类库 - 19.2 JQuery getter setter
- java静态代理和动态代理
- mysql命令行进入报错ERROR 2002 (HY000)
- 算法——TOP K问题最小堆实现
- 澳洲人赖特认怂 称不再想证明自己就是比特币发明人
- 开源控件NumberCircleProgressBar(圆形进度条)存在两条线的解决方法
- 安卓_高仿QQ
- select----1
- Android打开系统GPS设置页面代码
- NRF51修改MAC Address
- 【bzoj2878】[Noi2012]迷失游乐园 环套树概率dp
- 如何将杂乱无章的js文件格式化