代码 -- 堆排序 解决大数组找前K大。

来源:互联网 发布:psp转换视频软件 编辑:程序博客网 时间:2024/06/03 20:38
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;    }}