题9:前k个数

题目:

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);
            }
        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值