`
yeelor
  • 浏览: 409689 次
  • 性别: 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
分享到:
评论

相关推荐

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

    利用python,JavaScript,java,go,PHP等实现: 冒泡排序 选择排序 插入排序 希尔排序 归并排序 快速排序 堆排序 计数排序 桶排序 基数排序

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

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

    数据结构java版 排序算法

    总结的不错,值得一看 * 1.插入排序(直接插入排序、折半插入排序、希尔排序); * 2.交换排序(冒泡泡排序、快速排序); * 3.选择排序(直接选择排序、堆排序); * 4.归并排序; * 5.基数排序。

    java二分法排序源码-Article:十大经典排序算法动画,看我就够了!

    常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。 用一张图概括: 关于时间复杂度: 平方阶 (O(n2)) 排序 各类简单排序:直接插入、直接选择和冒泡排序。 ...

    java8源码-Large-File-Small-Memory-Sorting:大文件小内存排序

    大文件数据排序(基于归并排序) 开发工具及环境 IntelliJ IDEA; Java 8 启动说明 本机电脑内存大小为8G,因为Java创建对象在堆内分配内存,此时在启动脚本上设置-xms,来控制堆的大小, 因为模拟数据大概在4MB左右...

    java数据结构与算法第二版

    归并排序 消除递归 一些有趣的递归应用 小结 问题 实验 编程作业 第7章 高级排序 希尔排序 划分 快速排序 基数排序 小结 问题 实验 编程作业 第8章 二叉树 为什么使用二叉树? 树的术语 一个类比 ...

    Java数据结构和算法中文第二版

    归并排序 消除递归 一些有趣的递归应用 小结 问题 实验 编程作业 第7章 高级排序 希尔排序 划分 快速排序 基数排序 小结 问题 实验 编程作业 第8章 二叉树 为什么使用二叉树? 树的术语 一个类比 ...

    Java数据结构和算法(第二版)

    归并排序 消除递归 一些有趣的递归应用 小结 问题 实验 编程作业 第7章 高级排序 希尔排序 划分 快速排序 基数排序 小结 问题 实验 编程作业 第8章 二叉树 为什么使用二叉树? 树的术语 一个类比 二叉搜索树如何...

    数据结构与算法分析Java语言描述(第二版)

    堆6.6 左式堆6.6.1 左式堆性质6.6.2 左式堆操作6.7 斜堆6.8 二项队列6.8.1 二项队列结构6.8.2 二项队列操作6.8.3 二项队列的实现6.9 标准库中的优先队列小结练习参考文献第7章 排序7.1 预备知识7.2 插入排序7.2.1...

    Java数据结构和算法中文第二版(1)

    归并排序 清除递归 一些有趣的递归应用 小结 问题 实验 编程作业 第7章 高级排序 希尔排序 划分 快速排序 基数排序 小结 问题 实验 编程作业 第8章 二叉树 为什么使用二叉树? 树的术语 一个...

    数据结构与算法分析_Java语言描述(第2版)]

    堆6.6 左式堆6.6.1 左式堆性质6.6.2 左式堆操作6.7 斜堆6.8 二项队列6.8.1 二项队列结构6.8.2 二项队列操作6.8.3 二项队列的实现6.9 标准库中的优先队列小结练习参考文献第7章 排序7.1 预备知识7.2 插入排序7.2.1 ...

    数据结构(C语言版)\Java数据结构和算

    7.5 归并排序 7.6 堆排序 7.7 多关键字排序 7.8 链表排序和索引表排序 7.9 内部排序小结 7.10 外部排序 7.11 参考文献和选读材料 第8章 Hash法 8.1 引言 8.2 静态Hash法 8.3 动态Hash法 8.4 Bloom滤波器 ...

    数据结构与算法分析 Java语言描述第2版

    堆6.6 左式堆6.6.1 左式堆性质6.6.2 左式堆操作6.7 斜堆6.8 二项队列6.8.1 二项队列结构6.8.2 二项队列操作6.8.3 二项队列的实现6.9 标准库中的优先队列小结练习参考文献第7章 排序7.1 预备知识7.2 插入排序7.2.1 ...

    java 面试题 总结

    Collections是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作。 10、&和&&的区别。 &是位运算符,表示按位与运算,&&是逻辑运算符,表示逻辑与(and)。 11、HashMap...

    数据结构与算法分析_Java语言描述(第2版)

    7.6 归并排序 7.7 快速排序 7.7.1 选取枢纽元 7.7.2 分割策略 7.7.3 小数组 7.7.4 实际的快速排序例程 7.7.5 快速排序的分析 7.7.6 选择问题的线性期望时间算法 7.8 排序算法的一般下界 7.9 桶式排序 7.10 外部排序 ...

    数据结构与算法分析-Java语言描述(第2版)_2_2

    练习 参考文献第7章 排序 7.1 预备知识 7.2 插入排序 7.2.1 算法 7.2.2 插入排序的分析 7.3 一些简单排序算法的下界 7.4 希尔排序 7.5 堆排序 7.6 归并排序 7.7 快速排序 7.7.1 选取枢纽元 ...

    数据结构与算法分析-Java语言描述(第2版)_1_2

    练习 参考文献第7章 排序 7.1 预备知识 7.2 插入排序 7.2.1 算法 7.2.2 插入排序的分析 7.3 一些简单排序算法的下界 7.4 希尔排序 7.5 堆排序 7.6 归并排序 7.7 快速排序 7.7.1 选取枢纽元 ...

    数据结构与算法分析_Java_语言描述

    7.2.1 算法 7.2.2 插入排序的分析 7.3 一些简单排序算法的下界 7.4 希尔排序 7.5 堆排序 7.6 归并排序 7.7 快速排序 7.7.1 选取枢纽元 7.7.2 分割策略 7.7.3 小数组 7.7.4 实际的快速排序例程 ...

Global site tag (gtag.js) - Google Analytics