您的位置:首页 > 编程语言

代码 -- 堆排序 解决大数组找前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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: