使用优先级队列求一个大数组中的前k个最大的数(或前k个最小的数)

/**
 * 对于一个数据量很大的数组,找出数组中前k个最大的数和前k个最小的数
 */
package 华为机试题;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;

/**
 * @author Hutongling
 *
 * @time:2017年4月10日 下午9:12:25
 */
public class 优先级队列 {

    //找到数组中的前k个最小值
    static Queue<Integer> findFirstEndN(int[] data, int k){
        if(data==null || data.length==0)
            return null;

        Queue<Integer> priorityQueue=new PriorityQueue<>(k);
        for(int i=0;i<data.length;i++)
            priorityQueue.add(data[i]);
        return priorityQueue;

    }

    //找到数组中的前k个最大值
    static Queue<Integer> findTopN(int[] data, int k){
        if(data==null || data.length==0)
            return null;

        Queue<Integer> priorityQueue=new PriorityQueue<>(k);
        priorityQueue.add(data[0]);
        for(int i=1;i<data.length;i++){
            if(priorityQueue.size()<k)
                priorityQueue.add(data[i]);
            else if(data[i]>=priorityQueue.peek()){
                priorityQueue.poll();
                priorityQueue.add(data[i]);
            }
        }
        return priorityQueue;
    }

    //找到数组中的前k个最小值
    static Queue<Integer> findFirstEndN1(String filePath, int k) throws NumberFormatException, IOException{
        if(filePath==null)
            return null;

        Queue<Integer> priorityQueue=new PriorityQueue<>(k);
        File fileName= new File(filePath);
        BufferedReader bufread= new BufferedReader(new FileReader(fileName));
        String read;
        while((read=bufread.readLine())!=null){
            String[] data=read.split(" ");
            for(int i=0;i<data.length;i++)
                priorityQueue.add(Integer.valueOf(data[i]));
            read=null;
            data=null;
        }

        return priorityQueue;

    }

    // 找到数组中的前k个最大值
    static Queue<Integer> findTopN1(String filePath, int k) throws NumberFormatException, IOException {
        if (filePath == null)
            return null;

        Queue<Integer> priorityQueue = new PriorityQueue<>(k);// 建立一个优先级队列
        File fileName = new File(filePath);
        BufferedReader bufread = new BufferedReader(new FileReader(fileName));// 读入文件
        String read;
        while ((read = bufread.readLine()) != null) {
            String[] data = read.split(" ");
            priorityQueue.add(Integer.valueOf(data[0]));
            for (int i = 1; i < data.length; i++) {
                if (priorityQueue.size() < k)
                    priorityQueue.add(Integer.valueOf(data[i]));
                else if (Integer.valueOf(data[i]) >= priorityQueue.peek()) {
                    priorityQueue.poll();
                    priorityQueue.add(Integer.valueOf(data[i]));
                }
            }
            read = null;
            data = null;
        }
        return priorityQueue;
    }

    public static void main(String[] args) throws IOException {
        int[] data=new int[10000000];
        Random random=new Random();
        for(int i=0;i<data.length;i++)
            data[i]=random.nextInt(10000000);

        int k=15;
        Queue<Integer> priorityQueue=findFirstEndN(data,k);
        Queue<Integer> priorityQueueTop=findTopN(data,k);

        System.out.println("前k个最小的数为:");

        for(int i=0;i<k;i++)
            System.out.print(priorityQueue.poll() + " ");

        System.out.println("\n前k个最大的数为:");
        for(int i=0;i<k;i++)
            System.out.print(priorityQueueTop.poll() + " ");

        String path="D:/data1.txt";
        File text=new File(path);
        FileWriter textFile=new FileWriter(text);
        int n=10000000;
        for(int i=0;i<n;i++)
            if((i+1)%1000!=0)
                textFile.write(random.nextInt(10000000) + " ");
            else
                textFile.write(random.nextInt(10000000) + "\n");

        Queue<Integer> priorityQueue1=findFirstEndN1(path,k);
        Queue<Integer> priorityQueueTop1=findTopN1(path,k);

        System.out.println("前k个最小的数为:");

        for(int i=0;i<k;i++)
            System.out.print(priorityQueue1.poll() + " ");

        System.out.println("\n前k个最大的数为:");
        for(int i=0;i<k;i++)
            System.out.print(priorityQueueTop1.poll() + " ");
    }

}

代码结果:(每次运行的结果不一样,因为使用的是随机函数随机生成的一千万数据)
前k个最小的数为:
0 0 1 1 1 2 3 5 5 5 8 9 10 12 14
前k个最大的数为:
9999984 9999985 9999986 9999989 9999990 9999991 9999992 9999992 9999993 9999993 9999996 9999996 9999997 9999998 9999999 前k个最小的数为:
0 0 1 1 3 5 6 6 6 7 7 12 13 14 14
前k个最大的数为:
8467240 9976497 9977578 9983445 9985562 9986467 9988006 9988126 9988131 9988140 9988146 9988196 9988221 9988255 9988335

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值