Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 1080|回复: 0

多路归并排序 java实例

[复制链接]

该用户从未签到

发表于 2011-9-21 21:09:58 | 显示全部楼层 |阅读模式
对远远大于内存的数据进行外排序,在多路比较的时候用败者树效率会更高。
  1. package my.sort;
  2. import java.io.BufferedInputStream;
  3. import java.io.BufferedOutputStream;
  4. import java.io.BufferedWriter;
  5. import java.io.DataInputStream;
  6. import java.io.DataOutputStream;
  7. import java.io.File;
  8. import java.io.FileInputStream;
  9. import java.io.FileNotFoundException;
  10. import java.io.FileOutputStream;
  11. import java.io.FileWriter;
  12. import java.io.IOException;
  13. import java.util.ArrayList;
  14. import java.util.Arrays;
  15. import java.util.Iterator;
  16. import java.util.Random;
  17. /**
  18. * 基于大数据量的外排序算法,分为二路贵宾和多路归并
  19. * @author java2king
  20. * @link http://blog.csdn.net/Java2King
  21. *
  22. */
  23. public class ExternalSort {
  24.     public static int ITEM_COUNT = 10000000; //总数
  25.     public static int BUFFER_SIZE = 1024*4*1000;// 一次缓冲读取
  26.    
  27.     public static int FILE_COUNT = 1024*1000*1*4;// 每个文件的记录数1
  28.    
  29.     public static File MAIN_FILE = new File("mainset");//要排序的文件
  30.     /**
  31.      * 二路归并
  32.      * @param file
  33.      * @return
  34.      * @throws IOException
  35.      */
  36.     public File sort(File file) throws IOException {
  37.         ArrayList<File> files = split(file);
  38.         return process(files);
  39.     }
  40.     /**
  41.      * 多路归并
  42.      * @param file
  43.      * @throws IOException
  44.      */
  45.     public void mSort(File file) throws IOException{
  46.         ArrayList<File> files = split(file);
  47.         multipleMerge(files);
  48.         
  49.     }
  50.     // recursive method to merge the lists until we are left with a
  51.     // single merged list
  52.     private File process(ArrayList<File> list) throws IOException {
  53.         if (list.size() == 1) {
  54.             return list.get(0);
  55.         }
  56.         ArrayList<File> inter = new ArrayList<File>();
  57.         for (Iterator<File> itr = list.iterator(); itr.hasNext();) {
  58.             File one = itr.next();
  59.             if (itr.hasNext()) {
  60.                 File two = itr.next();
  61.                 inter.add(merge(one, two));
  62.             } else {
  63.               //  return one;
  64.                 inter.add(one);
  65.             }
  66.         }
  67.         return process(inter);
  68.     }
  69.     /**
  70.      * Splits the original file into a number of sub files.
  71.      */
  72.     private ArrayList<File> split(File file) throws IOException {
  73.         ArrayList<File> files = new ArrayList<File>();
  74.         int[] buffer = new int[FILE_COUNT];
  75.         FileInputStream fr = new FileInputStream(file);
  76.         BufferedInputStream bin = new BufferedInputStream(fr,BUFFER_SIZE);
  77.         DataInputStream din=new DataInputStream(bin);  
  78.         boolean fileComplete = false;
  79.         
  80.         while (!fileComplete) {
  81.             int index = buffer.length;
  82.             for (int i = 0; i < buffer.length && !fileComplete; i++) {
  83.                 try {
  84.                      buffer[i] = din.readInt();
  85.                 } catch (Exception e) {
  86.                     fileComplete = true;
  87.                     index = i;
  88.                 }
  89.             }
  90.             if (index != 0 && buffer[0] > -1) {
  91.                 Arrays.sort(buffer, 0, index);
  92.                 File f = new File("set" + new Random().nextInt());
  93.          //       File temp = File.createTempFile("josp", ".tmp", f);   
  94.                 FileOutputStream writer = new FileOutputStream(f);
  95.                 BufferedOutputStream bOutputStream = new BufferedOutputStream(writer);
  96.             
  97.                 DataOutputStream dout=new DataOutputStream(bOutputStream);
  98.                 for (int j = 0; j < index; j++) {
  99.                     dout.writeInt(buffer[j]);
  100.                 }
  101.                 dout.close();
  102.                 bOutputStream.close();
  103.                 writer.close();
  104.                 files.add(f);
  105.                
  106.             }
  107.         }
  108.         din.close();
  109.         bin.close();
  110.         fr.close();
  111.         return files;
  112.     }
  113.     /**
  114.      * 多路归并
  115.      * @param list
  116.      * @throws IOException
  117.      */
  118.     private void multipleMerge(ArrayList<File> list) throws IOException {
  119.         
  120.         int fileSize = list.size();
  121.         
  122.         if(fileSize == 1){
  123.             return;
  124.         }
  125.         
  126.         ArrayList<DataInputStream> dinlist = new ArrayList<DataInputStream>();
  127.         
  128.         int[] ext = new int[fileSize];//比较数组
  129.     //    File output = new File("multipleMerged");
  130.         FileOutputStream os = new FileOutputStream(MAIN_FILE);
  131.         BufferedOutputStream bout = new BufferedOutputStream(os);
  132.         DataOutputStream dout = new DataOutputStream(bout);
  133.         for (int i = 0; i < fileSize; i++) {
  134.         try {
  135.         dinlist.add(i, new DataInputStream(new BufferedInputStream(
  136.          new FileInputStream(list.get(i)), BUFFER_SIZE)));
  137.         } catch (Exception e) {
  138.                 e.printStackTrace();
  139.             }
  140.         }
  141.         int index = 0;
  142.         for (int i = 0; i < fileSize; i++) {
  143.             try {
  144.                 ext[i] = dinlist.get(i).readInt();
  145.             } catch (Exception e) {
  146.                 System.err.println("file_" + i + "为空");
  147.                 ext[i] = -1;
  148.             }
  149.         }
  150.         int count = fileSize;
  151.         int[] sum = new int[fileSize];
  152.         
  153.         while (count > 1) {
  154.             index = getMinIndex(ext);
  155.             dout.writeInt(ext[index]);
  156.             sum[index]++;
  157.             try {
  158.                 ext[index] = dinlist.get(index).readInt();
  159.             } catch (Exception e) {
  160.                 ext[index] = -1;
  161.                 count--;
  162.                 dinlist.get(index).close();
  163.         //        System.err.println(index + "空,写进:" +sum[index]);
  164.                
  165.             }
  166.         }
  167.         int sIndex = getSIndex(ext);
  168.         dout.writeInt(ext[sIndex]);
  169.         while (true) {
  170.             try {
  171.                 dout.writeInt(dinlist.get(sIndex).readInt());
  172.             } catch (Exception e) {
  173.                 dinlist.get(sIndex).close();
  174.                 break;
  175.             }
  176.         }
  177.         dout.close();
  178.     }
  179.     //找到剩下的最后一个文件输入流
  180.     public int getSIndex(int[] ext){
  181.         int result = 0;
  182.         for (int i = 0; i < ext.length; i++) {
  183.             if(ext[i]!= -1){
  184.                 result = i;
  185.                 break;
  186.             }
  187.         }
  188.         return result;
  189.     }
  190.     //找到数据中最小的一个
  191.     public int getMinIndex(int[] ext){
  192.         int min = 2147483647;
  193.         int index = -1;
  194.         for (int i = 0; i < ext.length; i++) {
  195.             if(ext[i] != -1 && ext[i] < min){
  196.                 min = ext[i];
  197.                 index = i;
  198.             }
  199.         }
  200.         return index;
  201.     }
  202.     /**
  203.      * 二路归并
  204.      *
  205.      * @param one
  206.      * @param two
  207.      * @return
  208.      * @throws IOException
  209.      */
  210.     private File merge(File one, File two) throws IOException {
  211.         FileInputStream fis1 = new FileInputStream(one);
  212.         FileInputStream fis2 = new FileInputStream(two);
  213.         BufferedInputStream bin1 = new BufferedInputStream(fis1,BUFFER_SIZE);
  214.         BufferedInputStream bin2 = new BufferedInputStream(fis2,BUFFER_SIZE);
  215.         
  216.         DataInputStream din1=new DataInputStream(bin1);  
  217.         DataInputStream din2=new DataInputStream(bin2);  
  218.         
  219.         File output = new File("merged" + new Random().nextInt());
  220.         FileOutputStream os = new FileOutputStream(output);
  221.         BufferedOutputStream bout = new BufferedOutputStream(os);
  222.         DataOutputStream dout=new DataOutputStream(bout);
  223.    
  224.         int a = -1;//= din1.readInt();
  225.         int b = -1;//= din2.readInt();
  226.         
  227.         boolean finished = false;
  228.         boolean emptyA = false;//
  229.         int flag = 0;
  230.         while (!finished) {
  231.             if (flag != 1) {
  232.                 try {
  233.                     a = din1.readInt();
  234.                 } catch (Exception e) {
  235.                     emptyA = true;
  236.                     break;
  237.                 }
  238.             }
  239.             if (flag != 2) {
  240.                 try {
  241.                     b = din2.readInt();
  242.                 } catch (Exception e) {
  243.                     emptyA = false;
  244.                     break;
  245.                 }
  246.             }
  247.             if(a > b){
  248.                 dout.writeInt(b);
  249.                 flag = 1;
  250.             }else if( a < b){
  251.                 dout.writeInt(a);
  252.                 flag = 2;
  253.             }else if(a == b){
  254.                 dout.write(a);
  255.                 dout.write(b);
  256.                 flag = 0;
  257.             }
  258.         }
  259.         finished = false;
  260.         if(emptyA){
  261.             dout.writeInt(b);
  262.             while(!finished){
  263.                 try {
  264.                     b = din2.readInt();
  265.                 } catch (Exception e) {
  266.                     break;
  267.                 }
  268.                 dout.writeInt(b);
  269.             }
  270.         }else{
  271.             dout.writeInt(a);
  272.             while(!finished){
  273.                 try {
  274.                     a = din1.readInt();
  275.                 } catch (Exception e) {
  276.                     break;
  277.                 }
  278.                 dout.writeInt(a);
  279.             }
  280.         }
  281.         dout.close();
  282.         os.close();
  283.         bin1.close();
  284.         bin2.close();
  285.         bout.close();
  286.         return output;
  287.     }
  288.   
  289.     /**
  290.      * @param args
  291.      * @throws IOException
  292.      */
  293.     public static void main(String[] args) throws IOException {
  294.               
  295.         Random random = new Random(System.currentTimeMillis());
  296.         FileOutputStream fw = new FileOutputStream(MAIN_FILE);
  297.         BufferedOutputStream bout = new BufferedOutputStream(fw);
  298.         DataOutputStream dout=new DataOutputStream(bout);  
  299.         
  300.         for (int i = 0; i < ITEM_COUNT; i++) {
  301.             int ger = random.nextInt();
  302.             ger = ger < 0 ? -ger : ger;
  303.             dout.writeInt(ger);
  304.         }
  305.         dout.close();
  306.         bout.close();
  307.         fw.close();
  308.         ExternalSort sort = new ExternalSort();
  309.         System.out.println("Original:");
  310.         long start = System.currentTimeMillis();
  311.         sort.mSort(MAIN_FILE);
  312.       
  313.         
  314.         long end = System.currentTimeMillis();
  315.         System.out.println((end - start)/1000 + "s");
  316.         recordFile((end - start)/1000 ,true);
  317.     }
  318.     private static void recordFile(long time,boolean isBuffer)
  319.             throws FileNotFoundException, IOException {
  320.         BufferedWriter bw = new BufferedWriter(new FileWriter("log",true));
  321.         bw.write("FILE_COUNT = "+FILE_COUNT+";对"+ ITEM_COUNT + "条数据 "+ ITEM_COUNT*4/(1024*1204) +"MB排序耗时:" + time + "s ");
  322.         if(isBuffer){
  323.             bw.write("  使用缓冲:"+BUFFER_SIZE*4/(1024*1204) +"MB");
  324.         }
  325.         bw.newLine();
  326.         bw.close();
  327.     }
  328. }
复制代码
回复

使用道具 举报

该用户从未签到

发表于 2011-9-25 10:05:26 | 显示全部楼层
不错的啊。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2024-6-17 14:17 , Processed in 0.353678 second(s), 34 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表