從10億個數據中,取出前1000個最大的數


采用小頂堆

public class TopN {

    /**
     * 找出數組arr中最大的前n個值,不要求這n個值有序
     */
    public static int[] topN(int[] arr, int n) {
        /**
         * 構建堆積
         */
        int[] list = new int[n];
        System.arraycopy(arr, 0, list, 0, n);
        // 在堆頂的始終是最小的值
        for (int i = 0; i < n; i++) {
            int t = i;
            while (t != 0 && list[parent(t)] > list[t]) {
                swap(list, t, t = parent(t));
            }
        }

        /**
         * 小頂堆
         */
        for (int i = n, len = arr.length; i < len; i++) {
            if (arr[i] >= list[0]) {
                // 置換棧頂
                list[0] = arr[i];
                // 調整棧頂
                int t = 0;
                // left(t) < n 防止下標越界
                while ((left(t) < n && list[t] > list[left(t)]) || (right(t) < n && list[t] > list[right(t)])) {
                    // 比較右節點和左節點值值,把小的節點值和父節點值對調
                    if (right(t) < n && list[right(t)] < list[left(t)]) {
                        swap(list, t, t = right(t));
                    } else {
                        swap(list, t, t = left(t));
                    }
                }
            }
        }
        return list;
    }

    private static void swap(int[] list, int i, int j) {
        int tmp = list[i];
        list[i] = list[j];
        list[j] = tmp;
    }

    /**
     * 父節點索引
     */
    private static int parent(int i) {
        return (i - 1) / 2;
    }

    /**
     * 左孩子索引
     */
    private static int left(int i) {
        return 2 * i + 1;
    }

    /**
     * 右孩子索引
     */
    private static int right(int i) {
        return 2 * i + 2;
    }

    public static void main(String[] args) {
        int[] arr = new int[] { 1, 2, 23, 4, 5, 11, 12, 13, 100 };
        System.out.println("原始數組: ");
        System.out.println(Arrays.toString(arr));
        System.out.println("調整后數組: ");
        System.out.println(Arrays.toString(TopN.topN(arr, 3)));
    }

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM