最小堆解决topK问题
2015-08-20 08:38
387 查看
package dataStructer; 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) / 2 - 1; i >= 0; i--) { // 对有孩子结点的元素heapify heapify(i); } } private void heapify(int i) { // 获取左右结点的数组下标 int l = left(i); int r = right(i); // 这是一个临时变量,表示 跟结点、左结点、右结点中最小的值的结点的下标 int smallest = i; // 存在左结点,且左结点的值小于根结点的值 if (l < data.length && data[l] < data[i]) smallest = l; // 存在右结点,且右结点的值小于以上比较的较小值 if (r < data.length && data[r] < data[smallest]) smallest = r; // 左右结点的值都大于根节点,直接return,不做任何操作 if (i == smallest) return; // 交换根节点和左右结点中最小的那个值,把根节点的值替换下去 swap(i, smallest); // 由于替换后左右子树会被影响,所以要对受影响的子树再进行heapify heapify(smallest);//左子结点被交换 那么做左子树需要重新排列 } // 获取右结点的数组下标 private int right(int i) { return (i + 1) << 1; } // 获取左结点的数组下标<<位置偏移 相当于倍数放大 private int left(int i) { return ((i + 1) << 1) - 1; } // 交换元素位置 private void swap(int i, int j) { int tmp = data[i]; data[i] = data[j]; data[j] = tmp; } // 获取对中的最小的元素,根元素 public int getRoot() { return data[0]; } // 替换根元素,并重新heapify public void setRoot(int root) { data[0] = root; heapify(0); } }
测试代码:
package dataStructer; public class TopK { // 从data数组中获取最大的k个数 private static int[] topK(int[] data,int k) { // 先取K个元素放入一个数组topk中 int[] topk = new int[k]; for(int i = 0;i< k;i++) { topk[i] = data[i]; } // 转换成最小堆 MinHeap heap = new MinHeap(topk); // 从k开始,遍历data for(int i= k;i<data.length;i++) { int root = heap.getRoot(); // 当数据大于堆中最小的数(根节点)时,替换堆中的根节点,再转换成堆 if(data[i] > root) { heap.setRoot(data[i]); } } return topk; } public static void main(String[] args) { // 源数据 int[] data = {56,275,12,6,45,478,41,1236,456,12,546,45}; // 获取Top5 int[] top5 = topK(data, 5); for(int i=0;i<5;i++) { System.out.println(top5[i]); } } }
相关文章推荐
- Linux中的cp命令
- 理解 OpenStack 高可用(HA)(5):RabbitMQ HA
- Docker 会取代虚拟机吗?
- linux文件上传下载笔记(rz,sz,sftp,scp)命令
- 第21/24周 性能监控(PAL工具)
- 【小熊刷题】Copy List with Random Pointer <可再复习思路>
- Chapter 1 OpenStack架构
- HTML编程、网站前台设计、网站后台开发
- hdu 5381 The sum of gcd (线段树x树状数组x区间和维护进阶x离线处理)
- loop
- optional
- 成为OpenStack工程师
- 关于OpenStack的学习路线及相关资源汇总
- openat函数的用法示例
- linux 信号详解
- Linux下查看在线用户及用户进程
- Linux下查看在线用户
- linux多线程编程详解
- Tomcat 8.0安装和使用
- 【Powershell】【计数器】实时获取邮箱服务器的队列