Java实现外部排序-数据结构综合设计实验三

目录

代码

Main类

GenerateFile类

ExtSort类

实验结果


依然是导入学校的包再完善的代码。

注意Main类和GenerateFile类里的路径。Ataraxia/extsort是我自己的配置,你可以自行修改,保证文件路径配套就可以。

代码

Main类

package cn.edu.bistu.cs.sort;

import org.apache.log4j.Logger;

import java.io.File;
import java.io.IOException;

public class Main {
    private static final Logger log = Logger.getLogger(Main.class);

    public static void main(String[] args) throws IOException {
        long start = System.currentTimeMillis();//开始计时
        //工作目录
        String working_dir = "C:/Users/Ataraxia/extsort/paixu";
        
        String sort_file = "C:/Users/Ataraxia/extsort/sort.txt";
        //排序结果
        String sort_result = "C:/Users/Ataraxia/extsort/result.txt";
        log.info("开始外部排序");
        ExtSort extSort = new ExtSort(11000,5);
        //升序排列
        String result = extSort.extSort(working_dir, sort_file, ExtSort.SortMode.ASC);
        File resultFile = new File(result);
        if(resultFile.renameTo(new File("C:/Users/Ataraxia/extsort/result.txt"))){
            log.info("排序完成,排序结果文件为:" + sort_result);
            log.info("排序耗时:"+(System.currentTimeMillis()-start)/1000.0+"秒");
        }else{
        	System.out.println("最终路径" + working_dir + sort_result);
            log.error("排序失败,最终结果文件重命名失败");
        }
        start = System.currentTimeMillis();
        log.info("开始检查排序算法正确性");
        if(extSort.check(working_dir,sort_file,sort_result,ExtSort.SortMode.ASC)){
            log.info("排序算法是正确的");
        }else{
            log.error("排序结果不正确!");
        }
        log.info("排序检查耗时:"+(System.currentTimeMillis()-start)/1000.0+"秒");
    }
}

GenerateFile类

package cn.edu.bistu.cs.sort;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;

/**
 * 生成一个包含大量整数的文件
 */
public class GenerateFile {

    public static void main(String[] args) throws IOException {
        File file = new File("C:/Users/Ataraxia/extsort/sort.txt");
        int numCount = 10000000;
        Random r = new Random();
        if (file.exists())
            file.delete();
        FileWriter fw = new FileWriter(file);
        for (int i = 0; i < numCount; i++) {
            fw.write(r.nextInt() + "\n");
        }
        fw.close();
    }
}

ExtSort类

package cn.edu.bistu.cs.sort;

import org.apache.log4j.Logger;

import java.io.*;
import java.util.*;

/**
 * Java外部排序程序
 */
public class ExtSort {

    public enum SortMode{
        /**
         * 升序
         */
        ASC,
        /**
         * 降序
         */
        DESC
    }

    private static final Logger log = Logger.getLogger(ExtSort.class);

    /**
     * 对原始待排序文件进行分割处理时,每批次数据的记录个数。
     */
    private int initial_batch_size;

    /**
     * 归并排序时的归并路数,即每一轮同时可以将几个文件进行归并
     */
    private int merge_degree;


    public ExtSort(int initial_batch_size, int merge_degree) {
        this.initial_batch_size = initial_batch_size;
        this.merge_degree = merge_degree;
    }


    /**
     * @param working_dir 工作目录
     * @param sort_file 待排序的原始文件
     * @param mode 排序模式,为ASC表示为升序排序(ascending),DESC为false表示为降序排序
     * @return 返回初始分割文件列表
     * @throws IOException 文件不存在或读写异常
     */
    private List<String> initialSortAndSplit(String working_dir, String sort_file, SortMode mode) throws IOException {
    	 List<String> fileNames = new ArrayList<>();
         List<Integer> batch = new ArrayList<>();
         int count = 1;
         try (BufferedReader reader = new BufferedReader(new FileReader(sort_file))) {
             String line;
             while ((line = reader.readLine()) != null) {
                 int num = Integer.parseInt(line);
                 batch.add(num);

                 if (batch.size() == initial_batch_size) {
                     batch.sort(mode == SortMode.ASC ? Comparator.naturalOrder() : Comparator.reverseOrder());
                     String fileName = working_dir + "/split" + count + ".txt";
                     count++;
                     try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
                         for (int n : batch) {
                             writer.write(String.valueOf(n));
                             writer.newLine();
                         }
                     }
                     fileNames.add(fileName);
                     batch.clear();
                 }
             }
         }

         if (!batch.isEmpty()) {
             batch.sort(mode == SortMode.ASC ? Comparator.naturalOrder() : Comparator.reverseOrder());
             String fileName = working_dir + "/split" + count + ".txt";
             try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
                 for (int num : batch) {
                     writer.write(String.valueOf(num));
                     writer.newLine();
                 }
             }
             fileNames.add(fileName);
             batch.clear();
         }
         return fileNames;

    }

    /**
     * @param working_dir 工作目录
     * @param sort_file 待排序的原始文件
     * @param mode 排序模式,为ASC表示为升序排序(ascending),DESC为false表示为降序排序
     * @return 排序完成后的结果文件名
     * @throws IOException 文件不存在或读写异常
     */
    public String extSort(String working_dir, String sort_file, SortMode mode) throws IOException {
        //将文件按照设定的批次数据大小进行初始切分并排序
        log.info("开始执行初始文件分割和排序");
        List<String> fileNames = initialSortAndSplit(working_dir, sort_file, mode);
        log.info("初始文件分割和排序执行完毕,共产生:"+fileNames.size()+"个分割文件");
        //执行归并排序
        int round = 1;
        do {
            log.info("第"+round+"轮归并排序开始,待归并文件剩余:"+fileNames.size());
            fileNames = mergeSort(working_dir, fileNames, mode);
            round++;
        } while (fileNames.size() > 1);
        return fileNames.get(0);
    }

    /**
     * 归并排序中的一轮,归并路数由merge_degree决定
     * @param working_dir 工作目录
     * @param fileNames 待归并的文件列表  C:/Users/Ataraxia/extsort/paixu/0.txt, C:/Users/Ataraxia/extsort/paixu/1.txt, C:/Users/Ataraxia/extsort/paixu/2.txt, C:/Users/Ataraxia/extsort/paixu/909.txt, 
     * @param mode 排序模式,为ASC表示为升序排序(ascending),DESC为false表示为降序排序
     * @return 归并后的文件列表
     * @throws IOException 文件不存在或读写异常
     */
    
    private List<String> mergeSort(String working_dir, List<String> fileNames, SortMode mode) throws IOException {
    	List<String> mergedFiles = new ArrayList<>();
    	int fileIndex = 0;
    	int count = 1;
    	while (fileIndex < fileNames.size()) {
    	List<String> batchFiles = new ArrayList<>();
    	        // 将merge_degree个文件进行归并
    	        for (int i = 0; i < merge_degree && fileIndex < fileNames.size(); i++) {
    	            batchFiles.add(fileNames.get(fileIndex));
    	            fileIndex++;
    	        }

    	        String mergedFileName = working_dir + "/merge" + count + ".txt";
    	        count++;
    	        mergeBatchFiles(batchFiles, mergedFileName, mode);
    	        mergedFiles.add(mergedFileName);
    	    }

    	    return mergedFiles;
    	}

    	private void mergeBatchFiles(List<String> fileNames, String mergedFileName, SortMode mode) throws IOException {
    	    PriorityQueue<BufferedReader> readers = new PriorityQueue<>(Comparator.comparingInt(this::readNextValue));
    	    BufferedWriter writer = new BufferedWriter(new FileWriter(mergedFileName));

    	    for (String fileName : fileNames) {
    	        BufferedReader reader = new BufferedReader(new FileReader(fileName));
    	        readers.add(reader);
    	    }

    	    while (!readers.isEmpty()) {
    	        BufferedReader reader = readers.poll();
    	        String line = reader.readLine();
    	        if (line != null) {
    	            writer.write(line);
    	            writer.newLine();
    	            readers.offer(reader);
    	        } else {
    	            reader.close();
    	        }
    	    }

    	    writer.close();
    	}

    	private int readNextValue(BufferedReader reader) {
    	    try {
    	        String line = reader.readLine();
    	        if (line != null) {
    	            return Integer.parseInt(line);
    	        }
    	    } catch (IOException e) {
    	        System.out.println("归并出错");
    	    }
    	    return Integer.MAX_VALUE;
    	}
    /**
     * 检查working_dir目录下的srcFile文件和sortedFile文件是否具有相同的整数集合,同时检查sortedFile文件是否是有序的。
     * @param working_dir 工作目录
     * @param srcFile 原始待排序文件
     * @param sortedFile 排序后的文件
     * @param mode 排序模式,为ASC表示为升序排序(ascending),DESC为false表示为降序排序
     * @return 若排序结果是正确的,返回true,否则返回false
     */
    public boolean check(String working_dir, String srcFile, String sortedFile, SortMode mode) throws IOException {
            //虽然老师没让做但我还是提一嘴,用BufferedReader对象去读结果文件,将每一行的数与        
            //前一行比较
    		return true;
    }

}

实验结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值