`
yeelor
  • 浏览: 416138 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

外部归并排序Java实现

    博客分类:
  • Java
 
阅读更多

 

 

package mergesort;

import java.text.DecimalFormat;
import java.util.Random;

public class Record {
	private int A;
	private String B;
	private String C;
	
	@Override
	public String toString() {
		String tempA = new  DecimalFormat("0000000000").format(this.A);
		return tempA+"#"+B+"#"+C;
	}
	
	public String getRecordString(){
		String A = new  DecimalFormat("0000000000").format(Math.abs( new Random().nextInt()));
		String B = "郭涛"+A;
		String C = "1111111111000000000011111111110000000000111111111100000000001111111111";
		return A+"#"+B+"#"+C;
	}
	

	public Record() {
		super();
	}

	public Record(String line) {
		super();
		String [] t = line.split("#");
		this.A = Integer.valueOf(t[0]);
		this.B = t[1];
		this.C = t[2];
	}


	public int getA() {
		return A;
	}


	public void setA(int a) {
		A = a;
	}


	public String getB() {
		return B;
	}


	public void setB(String b) {
		B = b;
	}


	public String getC() {
		return C;
	}


	public void setC(String c) {
		C = c;
	}
	
}

 

 

 

package mergesort;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;

/**
 * 生成一个具有10,000,000个记录的文本文件,其中每个记录由100个字节组成。实验只考虑记录的一个属性A,假定A为整数类型。
 * 记录在block上封装时,采用non-spanned方式,即块上小于一个记录的空间不使用。Block的大小可在自己的操作系统上查看,xp一般为4096 bytes。
 * 在内存分配50M字节的空间用于外部merge-sort。
 * 
 * @author GT 2012-10-16
 *
 */
public class MergeSort {
	private int size = 10000000;//总记录数10000000
	private int sizePerBlock = 40;//由于磁盘上每个block大小是4KB,每条记录大小为100B,所以每个block上记录条数为40
	private int sizePerMemory = 500000;//分配50M内存进行内存排序,每个记录大小100B,所以大概每次排序50W条记录,这里取个整数500000
	private int fileSize = size/sizePerMemory;//归并生成的小文件数   20
	private int blockSize = (size%sizePerBlock)==0?(size/sizePerBlock):(size/sizePerBlock)+1; //总的块数250000
	private int blockSizePerFile = (sizePerMemory%sizePerBlock)==0?(sizePerMemory/sizePerBlock):(sizePerMemory/sizePerBlock)+1; //每个小文件中的块数12500
	private int charBufferSizeOfReader = 4096; //第二阶段的排序中每个子列表使用一个block大小的缓冲区
	private int charBufferSizeOfWriter = 41943040; //第二阶段的排序中输出使用的缓冲区大小40M
	private String fileDirectory = "F:\\record3\\";
	private String recordFile = fileDirectory+"record.txt";
	
	
	private String sortedRecordFile = fileDirectory+"sorted_record.txt";
	
	public void creat() throws Exception{
		long start = new Date().getTime();
		BufferedWriter out = new BufferedWriter(new FileWriter(recordFile));
		for(int j = 0;j<blockSize;j++){
			for(int i =0;i<sizePerBlock;i++){
				out.write(new Record().getRecordString());
				out.newLine();
			}
			out.write(new char[94]);//填充94个byte
			out.newLine();//占两个byte
		}
	
		out.close();
		long end = new Date().getTime();
		System.out.println("生成数据耗时 :"+(end - start)+"ms");
		
	}
	
	public void read() throws Exception{
		BufferedReader in = new BufferedReader( new FileReader(recordFile));
		String line;
		
		for(int j = 0;j<blockSize;j++){
			for(int i =0;i<sizePerBlock;i++){
				line = in.readLine();
				Record r = new Record(line);
				System.out.println(r.getB());
			}
			in.readLine();
		}
		in.close();
		
	}
	
	Comparator<Record> comparator = new Comparator<Record>(){
		public int compare(Record r1,Record r2)
		{
			if(r1.getA()>=r2.getA()) return 1;
			else return 0;
		}
	};

	public void memorySort() throws Exception{
		long start = new Date().getTime();
		BufferedReader in = new BufferedReader( new FileReader(recordFile));
		
		String line;
		for(int k =0;k<fileSize;k++){//20
			Record records[] =  new Record[sizePerMemory];
			BufferedWriter out = new BufferedWriter(new FileWriter(fileDirectory+"record_"+k+".txt"));
			for(int j = 0;j<blockSizePerFile;j++){//12500
				for(int i =0;i<sizePerBlock;i++){//40
					line = in.readLine();
					records[j*sizePerBlock+i] =new Record(line);
				}
				in.readLine();
			}
			Arrays.sort(records,comparator);//主存排序
			
			for(int j = 0;j<blockSizePerFile;j++){//12500
				for(int i =0;i<sizePerBlock;i++){//40
					out.write(records[j*sizePerBlock+i].toString());
					out.newLine();
				}
				out.write(new char[94]);//填充94个byte
				out.newLine();//占两个byte
			}
			out.close();
		}
		in.close();
		long end = new Date().getTime();
		System.out.println("内存排序耗时 :"+(end - start)+"ms");
	}
	
	public void mergeSort() throws Exception{
		long start = new Date().getTime();
		BufferedWriter out = new BufferedWriter(new FileWriter(sortedRecordFile),charBufferSizeOfWriter);
		BufferedReader in [] = new BufferedReader[fileSize];
		for(int i =0;i<fileSize;i++){
			in[i] = new BufferedReader( new FileReader(fileDirectory+"record_"+i+".txt"),charBufferSizeOfReader);
		}
		Record rs[] = new Record[fileSize];
		Boolean finish [] = new Boolean[fileSize];
		for(int i =0;i<fileSize;i++) {
			rs[i]=new Record(in[i].readLine());
			finish[i]= false;
		}
		Record min;
		String line;
		int finishCount = 0;
		int count = 0;
		while(true){
			
			int firstFalse = 0;//找到第一个没有写完的文件序列值
			for(int i=0;i<fileSize;i++){
				if(finish[i]==true)
					firstFalse =i+1;
				else
					break;
			}
			if(firstFalse>=fileSize) break;
			if(finishCount>=fileSize) break;
			min = rs[firstFalse];
			int j =firstFalse;
			
			for(int i =firstFalse+1;i<fileSize;i++){
				if(!finish[i]&&(rs[i].getA()<min.getA())){
					min = rs[i];
					j = i;
				}
			}
			if((count!=0)&&(count%sizePerBlock==0)){
				out.write(new char[94]);//填充94个byte
				out.newLine();//占两个byte
			}
			out.write(min.toString());
			out.newLine();
			
			
			if(!finish[j]){
				line = in[j].readLine();
				if(line!=null){
					if("".equals(line.trim()))
					{
						line = in[j].readLine();
						if(line==null){
							finish[j] = true;
							finishCount++;
						}
					}else {
						rs[j]= new Record(line);
					}
				}else {
					finish[j] = true;
					finishCount++;
				}
			}
			count++;
		}
		
		for(int i =0;i<fileSize;i++){
			in[i].close();
		}
		out.close();
		
		long end = new Date().getTime();
		System.out.println("外存排序耗时 :"+(end - start)+"ms");	
	}
	
	public static void main(String [] args) throws Exception{

//		long start = new Date().getTime();
		MergeSort ms = new MergeSort();
//		ms.creat();
//		ms.read();
//		ms.memorySort();
		ms.mergeSort();
		
//		long end = new Date().getTime();
//		System.out.println("the time is :"+(end - start)+"ms");

	}
}

 

 

3
0
分享到:
评论

相关推荐

    归并排序(JAVA)

    在Java中实现归并排序,我们可以将一个大数组分成两个小数组,分别对它们进行排序,然后将排序后的子数组合并成一个有序的大数组。这个过程会递归地进行,直到每个子数组只包含一个元素,因为单个元素天生就是有序的...

    java归并排序

    在Java中实现归并排序,我们可以分别实现递归版和非递归版,这两种方法各有其特点和适用场景。 ### 1. 分治策略 归并排序的核心是分治法,它将一个大数组分为两个相等或接近相等的子数组,分别对这两个子数组进行...

    Java实现归并排序算法(源代码)

    ### Java实现归并排序算法(源代码)知识点详解 #### 一、归并排序概述 归并排序是一种经典的排序算法,其核心思想是分而治之。它将一个大问题分解为若干个相同的小问题来解决,最终通过合并这些小问题的解来得到...

    归并排序介绍和java代码实现

    归并排序是一种高效的排序算法,基于分治策略。它的核心思想是将大问题分解为小问题,然后逐一解决,最后将结果合并。...通过理解其工作原理和Java实现,开发者可以在实际项目中灵活运用归并排序来优化算法性能。

    java实现归并排序算法

    在Java中,我们可以看到一个典型的归并排序实现。`mergeSort()`方法是归并排序的主函数,它接受一个整数数组`a`,一个临时数组`tmp`以及两个表示子序列范围的索引`left`和`right`。`mergeSort()`首先检查左边界是否...

    java归并外排序

    Java实现归并外排序时,通常会用到以下几个关键类和方法: - `FileReader` 和 `BufferedReader`:用于读取文件。 - `FileWriter` 和 `BufferedWriter`:用于写入文件。 - `ArrayList` 或其他集合类:存储块中的数据...

    归并排序的原理及java代码实现

    Java中实现归并排序通常包括以下步骤: 1. 定义一个方法`sort()`,接受一个整型数组、起始下标`low`和结束下标`high`作为参数。如果`low`小于`high`,则说明数组还需要继续分割。 2. 计算中间下标`mid`,将数组分成...

    史上最清晰、最详细的归并排序算法详解:Java示例代码和逻辑解析 保证你是小白也能看懂

    虽然这比O(1)的空间复杂度高,但其稳定的性能和可预测的时间复杂度使得归并排序在特定场景下非常有用,比如在外部排序中,由于磁盘I/O操作的代价较大,归并排序的性能优势更为明显。 6. **适用场景:** 归并排序...

    归并排序实现

    3. 适用于外部排序:由于其分治特性,归并排序在处理大型文件或磁盘数据时表现出色。 缺点: 1. 空间需求:归并排序需要额外的存储空间,对于内存有限的环境不友好。 2. 不适合小规模数据:对于小规模数据,其初始...

    算法-理论基础- 排序- 归并排序(包含源程序).rar

    2. 归并排序的源代码实现,可能是C++、Java、Python或其他编程语言。 3. 对归并排序算法的性能分析,包括时间复杂度和空间复杂度的讨论。 4. 实际应用示例,展示如何在实际编程中使用归并排序。 5. 归并排序与其他...

    排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录

    5. 归并排序:归并排序采用分治策略,将数组拆分为两半,分别排序后再合并。由于始终需要额外的空间,归并排序是稳定的排序算法,时间复杂度为O(n log n)。 6. 快速排序:快速排序的核心是“分而治之”,通过选取一...

    JAVA写的6种内部排序算法简单实现

    这六种排序算法可能包括常见的快速排序、归并排序、插入排序、选择排序、冒泡排序以及堆排序。接下来,我们将对每一种排序算法进行详细介绍,并结合Java代码示例进行解析。 1. 插入排序(Insertion Sort) 插入排序...

    Java 大文件读取排序

    而对于大数据,归并排序更为合适,因为它可以在外部存储器(如硬盘)上进行,且具有稳定的性能。在Java中,我们可以使用Collections.sort()方法,但为了处理大文件,可能需要自定义一个适配外部排序的版本。 此外,...

    java排序算法实现

    本篇主要关注内部排序,它包括五种主要类型:插入排序、选择排序、交换排序、归并排序和分配排序。 插入排序是一种简单直观的排序算法,分为直接插入排序。其基本思想是将未排序的元素逐个插入到已排序的序列中。以...

    常用数据结构及其算法的Java实现

    本项目主要使用Java实现各种经典常用数据结构及其算法,包括但不仅限于链表、栈,队列,树,图等经典数据结构。 八大排序算法及其实现,具体包括直接插入排序,希尔排序,直接选择排序,堆排序,冒泡排序,快速排序...

    数据结构java版 排序算法

    - 当数据规模较大时,为了追求更好的时间复杂度,应选用快速排序、堆排序或归并排序,它们的时间复杂度为O(nlogn)。 - 快速排序通常性能较好,但在最坏情况下(如数据已经完全有序),效率较低。堆排序在任何情况下...

    各种排序算法java实现

    标题中的“各种排序算法java实现”意味着我们将探讨Java编程语言中实现的不同排序算法。排序算法是计算机科学的基础,它们在处理数据时起着至关重要的作用,尤其是在大数据和高性能计算领域。Java提供了多种内置方法...

    归并排序

    在Java中实现归并排序,我们可以创建一个名为`MergeSort`的类,并在其中定义一个`mergeSort()`方法。这个方法首先检查数组的长度,如果长度为1或更小,那么数组已经排序,直接返回。否则,它会递归地将数组分为两...

    java代码-归并排序-Java

    在Java中,实现归并排序可以使用以下方法: ```java public class MergeSort { public void merge(int[] arr, int left, int mid, int right) { // 创建临时数组 int[] temp = new int[right - left + 1]; int ...

Global site tag (gtag.js) - Google Analytics