排序算法---外部排序
2017-08-03 13:46
176 查看
算法设计:
可以使用外部排序对大容量数据进行排序。数据量过大,存储于外部文件,数据不能完全加载到内存中。 1.从文件中读取一固定数目的数据到数组,对数组排序,将排好序的数组作为一个数据段输出到一个临时文件,重复上述过程,直到源文件中数据读取完 2.将存储了数据段的文件中一般的数据段复制到一个临时文件,然后对着两个文件的数据段归并排序,每两个数据段归并形成一个大的数据段存储于一个文件中,重复2,直到只有一个数据段为止。
[b]代码实现:[/b]
创建存储大量数据的文件:
public class CreateLargeFile { public static void main(String[] args) throws IOException { DataOutputStream output = new DataOutputStream( new BufferedOutputStream(new FileOutputStream("D:\\largedata.dat"))); for (int i = 0; i < 800004; i++) output.writeInt((int) (Math.random() * 1000000)); output.close(); DataInputStream input = new DataInputStream(new BufferedInputStream(new FileInputStream("D:\\largedata.dat"))); for (int i = 0; i < 100; i++) System.out.print(input.readInt() + " "); input.close(); } }
排序实现:
public class SortLargeFile { public static final int MAX_ARRAY_SIZE = 100000; public static final int BUFFER_SIZE = 100000; public static void main(String[] args) throws IOException { // 将largedata.dat中的数据排序存入sortedfile.dat中 sort("D:\\largedata.dat", "D:\\sortedfile.dat"); // 输出排序后的前100个数 displayFile("D:\\sortedfile.dat"); } /** * 将源文件数据排序存入目标文件 * * @param sourcefile * @param targetfile * @throws IOException */ public static void sort(String sourcefile, String targetfile) throws IOException { int numberOfSegments = initializeSegments(MAX_ARRAY_SIZE, sourcefile, "D:\\f1.dat"); merge(numberOfSegments, MAX_ARRAY_SIZE, "D:\\f1.dat", "D:\\f2.dat", "D:\\f3.dat", targetfile); } /** * 将原始文件排序为一个个有顺序的段,存入临时文件 * * @param segmentSize * @param originalFile * @param f1 * @return * @throws IOException */ private static int initializeSegments(int segmentSize, String originalFile, String f1) throws IOException { int[] list = new int[segmentSize]; DataInputStream input = new DataInputStream(new BufferedInputStream(new FileInputStream(originalFile))); DataOutputStream output = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(f1))); int numberOfSegments = 0; while (input.available() > 0) { numberOfSegments++; int i = 0; for (; input.available() > 0 && i < segmentSize; i++) { list[i] = input.readInt(); } // 将读出的数据排序 Arrays.sort(list, 0, i); // 将排序后的数据输入临时文件 for (int j = 0; j < i; j++) { output.writeInt(list[j]); } } input.close(); output.close(); return numberOfSegments; } /** * 将排好序的段归并并排序直到只有一个段 * * @param numberOfSegments * @param segmentSize * @param f1 * @param f2 * @param f3 * @param targetfile * @throws IOException */ private static void merge(int numberOfSegments, int segmentSize, String f1, String f2, String f3, String targetfile) throws IOException { if (numberOfSegments > 1) { mergeOneStep(numberOfSegments, segmentSize, f1, f2, f3); merge((numberOfSegments + 1) / 2, segmentSize * 2, f3, f1, f2, targetfile); } else { File sortedFile = new File(targetfile); if (sortedFile.exists()) sortedFile.delete(); new File(f1).renameTo(sortedFile); } } /** * 归并第一阶段 * * @param numberOfSegments * @param segmentSize * @param f1 * @param f2 * @param f3 * @throws IOException */ private static void mergeOneStep(int numberOfSegments, int segmentSize, String f1, String f2, String f3) throws IOException { DataInputStream f1Input = new DataInputStream(new BufferedInputStream(new FileInputStream(f1), BUFFER_SIZE)); DataOutputStream f2Output = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(f2), BUFFER_SIZE)); // 将f1中的段复制一半到f2中 copyHalfToF2(numberOfSegments, segmentSize, f1Input, f2Output); f2Output.close(); // 将f1和f2中的段归并为更大的段到f3中 DataInputStream f2Input = new DataInputStream(new BufferedInputStream(new FileInputStream(f2), BUFFER_SIZE)); DataOutputStream f3Output = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(f3), BUFFER_SIZE)); mergeSegments(numberOfSegments / 2, segmentSize, f1Input, f2Input, f3Output); f1Input.close(); f2Input.close(); f3Output.close(); } /** * 复制前半部分的段 * * @param numberOfSegments * @param segmentSize * @param f1Input * @param f2Output * @throws IOException */ private static void copyHalfToF2(int numberOfSegments, int segmentSize, DataInputStream f1Input, DataOutputStream f2Output) throws IOException { for (int i = 0; i < (numberOfSegments / 2) * segmentSize && f1Input.available() > 0; i++) { f2Output.writeInt(f1Input.readInt()); } } /** * 归并所有的段 * * @param numberOfSegments * @param segmentSize * @param f1Input * @param f2Input * @param f3Output * @throws IOException */ private static void mergeSegments(int numberOfSegments, int segmentSize, DataInputStream f1Input, DataInputStream f2Input, DataOutputStream f3Output) throws IOException { for (int i = 0; i < numberOfSegments; i++) { mergeTwoSegments(segmentSize, f1Input, f2Input, f3Output); } // 如果f1中还有剩余的则复制到f3 while (f1Input.available() > 0) { f3Output.writeInt(f1Input.readInt()); } } /** * 归并两个分段 * * @param segmentSize * @param f1 * @param f2 * @param f3 * @throws IOException */ private static void mergeTwoSegments(int segmentSize, DataInputStream f1, DataInputStream f2, DataOutputStream f3) throws IOException { int intFromF1 = f1.readInt(); int intFromF2 = f2.readInt(); int f1Count = 1; int f2Count = 1; while (true) { if (intFromF1 < intFromF2) { f3.writeInt(intFromF1); if (f1.available() == 0 || f1Count++ >= segmentSize) { f3.write(intFromF2); break; } else intFromF1 = f1.readInt(); } else { f3.writeInt(intFromF2); if (f2.available() == 0 || f2Count++ >= segmentSize) { f3.write(intFromF1); break; } else intFromF2 = f2.readInt(); } } while (f1.available() > 0 && f1Count++ < segmentSize) { f3.write(f1.readInt()); } while (f2.available() > 0 && f2Count++ < segmentSize) { f3.write(f2.readInt()); } } public static void displayFile(String fileName) { try { DataInputStream input = new DataInputStream(new FileInputStream(fileName)); for (int i = 0; i < 100; i++) { System.out.print(input.readInt() + " "); } input.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
相关文章推荐
- 【排序算法】外部排序一 —— 外部排序介绍
- 【排序算法】外部排序二 —— 外部排序技术之多路归并
- 海量数据排序,多路平衡归并算法及实现(外部文件排序算法)
- 经典排序算法--选择排序
- 排序算法:推排序
- 排序算法(一)---- 直接插入排序
- 基数排序!一种美妙实用高效的排序算法!
- 排序算法四:选择排序
- 外部排序,杀鸡焉用牛刀?
- 几种排序算法的C++实现——快速排序、堆排序、基数排序
- 外部排序的基本思路
- 外部排序技术之多路归并
- 排序算法--快速排序
- [排序算法]:Java实现选择排序和插入排序
- 排序算法之快速排序-Java-version
- 一个o(n)的排序算法,类位图排序
- 常见排序算法(四)(基数排序、桶排序)
- 排序算法总结(四)快速排序【QUICK SORT】
- 排序算法总结之直接选择排序
- 排序算法(二)--交换排序之起泡排序,快速排序