题目:
1.求海量数据(正整数)按逆序排列的前k个数( topk ),因为数据量太大,不能全部存储在内存中,只能一个一个地从磁盘或者网络上读取数据,请设计一个高效的算法来解决这个问题
2.不限制用户输入数据个数,用户每输入一个数据就回车使得程序可立即获得这个数据,用户输入-1代表输入终止
然后用户输入K,代表要求得topK
请输出topk,从小到大,空格分割
package 分治法;
import java.util.Arrays;
import java.util.Scanner;
/**
* >求海量数据(正整数)按逆序排列的前k个数( topk ),因为数据量太大,不能全部存储在内存中,只能一个一个地从磁盘或者网络上读取数据,请设计一个高效的算法来解决这个问题
* >不限制用户输入数据个数,用户每输入一个数据就回车使得程序可立即获得这个数据,用户输入-1代表输入终止
* >第一行:然后用户输入K,
* 随后的N行(不限制)代表用户输入的数据
* 代表要求得topK
* 用户输入-1代表终止
* >请输出topk,从小到大,空格分割
*/
public class case09_前k个数 {
static int[] heap;//堆
static int index =0;//记录堆的元素个数
static int k;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
k=sc.nextInt();
heap=new int[k];
int x=sc.nextInt();
while(x!=-1){
deal(x);//x不等于-1处理x使得堆为小顶堆
x=sc.nextInt();//用户输入下一个数
}
printRs();//处理完后输出
}
private static void printRs() {
System.out.println(Arrays.toString(heap));
}
/**
* 如果数组数据量小于等于k,直接加入堆中
* 等于k的时候进行堆化
* @param x
*/
private static void deal(int x) {
if(index <k){
heap[index++]=x;
if(index ==k){
//堆化
MinHeap(heap);
}
}else
//x和堆顶进行比较,x大于堆顶,将堆顶替换掉,并向下调整
if(heap[0]<x){
heap[0]=x;
MinHeapFixDown(heap,0,k);
printRs();
}
}
public static void MinHeap(int[] A) {
int n = A.length;
for (int i = n / 2 - 1; i >= 0; i--) {
MinHeapFixDown(A, i,n);
}
System.out.println("A = " + Arrays.toString(A));
}
public static void MinHeapFixDown(int[] A, int i, int n) {
//先找到左右孩子
int left = 2 * i + 1;
int right = 2 * i + 2;
//左右孩子已经越界,i就是叶子节点
if (left > n) {
return;
}
int min = left;
if (right > n) {
min = left;
} else {
if (A[right] < A[left]) {
min = right;
//如果A[i]比两个孩子都小,不用调整
if (A[i] <= A[min]) {
return;
}
//否则,找到两个孩子中较小的,和i做交换
int temp = A[i];
A[i] = A[min];
A[min] = temp;
//小孩子那个位置的值发生了变化,i的值变更为小孩子那个位置的下标,递归调整
MinHeapFixDown(A, min, n);
}
}
}
}