代码 -- 堆排序 解决大数组找前K大。
2017-09-04 18:41
211 查看
public class Main { public static void main(String[] args) { //用来模拟的输入数组 int[] input = new int[] {1,6,5,2,7,10,86,21,89,10,87,10,81,3,88,10,123,56,21, 31,465,31,634,321,564,6987,21,1,1,2,3,5,46,6874,63541,321,321, 54,32,654,87,365,321,574,687,321,21,653,987,31,321}; //求前K大 int K = 10; //构建一个数组来存结果 int[] result = new int[K]; //将输入的前K个存入数组,并构建小顶堆(二叉堆) for(int i = 0;i<K;i++){ result[i] = input[i]; int index = i; //判断父节点是不是比刚插入的这个节点大,如果大,则调整(交换)。 while(index != 0 && result[index] < result[getParent(index)]){ result = swap(result, index, getParent(index)); index = getParent(index); } } //接下来将input数组中的数字从 下标为K 开始插入堆,如果比堆顶小,则丢弃。 for(int i = K;i<input.length;i++){ if(input[i] < result[0]) continue; //用index来存储当前插入进堆中的树的下标。会首先插入在堆顶(原堆顶被遗弃) int index = 0; result[0] = input[i]; //如果左子节点存在的话,则开始判断调整,左子节点不存在,有子节点必定不存在。 while(getLeftSon(result, index)!= -1){ //用swap来保存应该跟哪个子节点交换,如果为0,则不动,为1,交换左,为2,交换右。 int swap = 0; //如果右子节点不为空,左子节点必定不为空。 if(getRightSon(result, index)!= -1){ //如果当前节点比两个子节点都要大,则与较小的交换。 if(result[index] > result[getLeftSon(result, index)] && result[index] > result[getRightSon(result, index)]){ if(result[getLeftSon(result, index)] < result[getRightSon(result, index)]) swap = 1; else swap = 2; } //如果只比左节点大,则交换左 else if(result[index] > result[getLeftSon(result, index)]) swap = 1; //如果只比有节点大,交换右 else if(result[index] > result[getRightSon(result, index)]) swap = 2; } else{ //如果只比左节点大,则交换左 if(result[index] > result[getLeftSon(result, index)]) swap = 1; } //进行交换 switch (swap) { case 1: result = swap(result, index, getLeftSon(result, index)); index = getLeftSon(result, index); break; case 2: result = swap(result, index, getRightSon(result, index)); index = getRightSon(result, index); break; default: break; } if(swap == 0){ break; } } } for (int i : result) { System.out.println(i); } } //获得父亲节点,父亲节点序号为(x - 1)/ 2 public static int getParent(int x){ return (int)((x - 1)/2); } //获得左子节点,序号为2*x + 1,如果不存在,则返回 - 1 public static int getLeftSon(int[] arr,int x){ if(2*x + 1< arr.length ) return 2*x + 1; return -1; } //获得左子节点,序号为2*x + 2,如果不存在,则返回 - 1 public static int getRightSon(int[] arr,int x){ if(2*x+2 < arr.length) return 2*x + 2; return -1; } //交换 public static int[] swap(int[] arr, int x, int y) { int temp; temp = arr[x]; arr[x] = arr[y]; arr[y] = temp; return arr; } }
相关文章推荐
- Java代码解决两个数组归并问题
- 修改一行代码,解决在C++ Builder平台上JSONCPP向数组添加元素的Bug
- 数组排序面试题php解决代码
- 一行代码解决 sql语句 in传入数组变字符串
- 不用concat解决Javascript连接多个数组
- 将地图服务导出成经续度数组代码(supermap版本)
- eclipse使用dark主题后,pydev插件代码编辑时选中的代码显示看不清楚的解决办法
- Discuz!uc.key泄露导致代码注入漏洞uc.php的解决方法
- dbn_svr代码遇到的问题及解决办法
- win7笔记本电脑出现蓝屏错误代码0x00000077常见原因及解决方法
- var_dump() 打印数组不完整 解决办法
- Git:代码冲突常见解决方法
- linux服务器上的php代码通过nginx发布,解决pathinfo模式问题
- 用户 'sa' 登录失败。该用户与可信 SQL Server 连接无关联'。错误代码:18452 解决办法
- 二行代码解决全部网页木马
- 解决Windows 2000不支持Response.CodePage代码的问题
- TFS签入代码时,自动修改工作项的状态为“已解决”
- 【转】iis解决应用程序池**提供服务的进程意外终止进程ID是**。进程退出代码是'0x80'
- MyEclipse 代码自动提示功能失效 提示No Default Proposals 或 no completions available 的解决方法
- Eclipse中格式化代码快捷键Ctrl+Shift+F失效的解决办法