逆序排列前K个数,因为数据量太大,不能全部存储再内存中,只能一个一个地从磁盘或者网络上读取数据,设计一个高效地算法来解决这个问题。
不限制用户输入数据的个数,用户每输入一个数据就回车,使得程序可以立即获取这个数据,用户输入-1代表终止。
然后用户输入K,代表要求得到的TOPK
public class Xiaodingdui {
static int index=0;
static int[] heap;
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=sc.nextInt();
}
System.out.println(Arrays.toString(heap));
}
private static void deal(int x) {
if(index<k){
heap[index++]=x;
//当topK存满则进行堆化(小顶堆)
if(index==k){
buildMinHeap(heap,heap.length);
}
}else {
if(heap[0]<x){
heap[0]=x;
minHeadAdjust(heap,0,heap.length);
}
}
}
private static void buildMinHeap(int[] heap, int length) {
//减一因为0号位也存有元素
for (int i = length/2-1; i >0 ; i--) {
minHeadAdjust(heap,i,heap.length);
}
}
private static void minHeadAdjust(int[] heap, int i, int length) {
//找到左右孩子
int left=i*2+1;
int right=i*2+2;
//该节点为叶子节点
if(left>=length){
return;
}
//寻找孩子节点中最小的一个
int min=left;
if(right<length&&heap[right]<heap[left]){
min=right;
}
if(heap[i]<=heap[min]){
return;
}else {
int temp=heap[i];
heap[i]=heap[min];
heap[min]=temp;
}
minHeadAdjust(heap,min,heap.length);
}
}
结果如下: