轉載自java實現Top n算法基礎,和Java高效讀取大文件
採用小頂堆或者大頂堆:
數據描述:求最大K個採用小頂堆,而求最小K個採用大頂堆。
實現步驟:根據數據前K個建立K個節點的小頂堆,在後面的N-K的數據的掃描中,
如果數據大於小頂堆的根節點,則根節點的值覆爲該數據,並調節節點至小頂堆。
如果數據小於或等於小頂堆的根節點,小根堆無變化。
求最小K個跟這求最大K個類似。時間複雜度O(nlogK)(n:數據的長度),特別適用於大數據的求Top K。
package com.java.algorithm.test; import java.io.FileInputStream; import java.io.IOException; import java.util.Scanner; /** * 求前面的最大K個 解決方案:小根堆 * (數據量比較大(特別是大到內存不可以容納)時,偏向於採用堆) */ public class TopKByHeap { /** * 創建k個節點的小根堆 * * @param a * @param k * @return */ int[] createHeap(int a[], int k) { int[] result = new int[k]; for (int i = 0; i < k; i++) { result[i] = a[i]; } for (int i = 1; i < k; i++) { int child = i; int parent = (i - 1) / 2; int temp = a[i]; while (parent >= 0 && child != 0 && result[parent] > temp) { result[child] = result[parent]; child = parent; parent = (parent - 1) / 2; } result[child] = temp; } return result; } void insert(int a[], int value) { a[0] = value; int parent = 0; while (parent < a.length) { int lchild = 2 * parent + 1; int rchild = 2 * parent + 2; int minIndex = parent; if (lchild < a.length && a[parent] > a[lchild]) { minIndex = lchild; } if (rchild < a.length && a[minIndex] > a[rchild]) { minIndex = rchild; } if (minIndex == parent) { break; } else { int temp = a[parent]; a[parent] = a[minIndex]; a[minIndex] = temp; parent = minIndex; } } } /*** * 從數組中加載數據並計算topN * @param input 源數據,用於計算topN的數組 * @param k topN中具體N的值 * @return */ int[] getTopKByHeap(int input[], int k) { int heap[] = this.createHeap(input, k); for (int i = k; i < input.length; i++) { if (input[i] > heap[0]) { this.insert(heap, input[i]); } } return heap; } /**從文件中加載數據並計算topN * 假設文件中一行數據格式爲:商品名稱/t 商品價格 * * @param path 文件路徑 */ public int[] readDataFromBigFile(String path, int k) throws IOException { FileInputStream inputStream = null; Scanner sc = null; int[] result = new int[k]; int index = 0; try { inputStream = new FileInputStream(path); sc = new Scanner(inputStream, "UTF-8"); while (sc.hasNextLine()) { String line = sc.nextLine(); String[] vals = line.split("\\s"); int price = Integer.parseInt(vals[1]); if (index >= k) { this.insert(result, price); } else { result[index++] = price; if (index == k) { result = createHeap(result, k); } } } // note that Scanner suppresses exceptions if (sc.ioException() != null) { throw sc.ioException(); } } catch (Exception e) { e.printStackTrace(); } finally { if (inputStream != null) { inputStream.close(); } if (sc != null) { sc.close(); } } return result; } public static void main(String[] args) { int a[] = {4, 3, 5, 1, 2, 8, 9, 10}; int result[] = new TopKByHeap().getTopKByHeap(a, 3); for (int temp : result) { System.out.println(temp); } } }