如何给大数据量的磁盘文件排序
来源:互联网 发布:python 抓到的源码不对 编辑:程序博客网 时间:2024/05/20 02:26
本文是学习 july博客中的如何给 10^7个数据量的磁盘文件排序,这一文章的学习文章。
July博客
问题:
输入:给定一个文件,里面有 最多n个不重复的正整数,其中每个数都小于等于n, n= 10^7
输出:得到按小到大升序排列的包含所有输入的整数的列表
条件:1M内存空间,时间5分钟以下,10s最佳
分析:
解法1 : 编程猪机上说的 位图法
java代码实现如下:
由于1 M 有 8 388 068 bit,代表放不下,所以要分开两部分。
当中需要使用java bitset类 , 为什么要用BitSet
import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileReader;import java.io.FileWriter;import java.util.BitSet;public class bitsetuse {static int max_each_scan = 5000000;public static void main(String[] args) throws Exception{BitSet bs = new BitSet(max_each_scan); BufferedReader bis = new BufferedReader(new FileReader("dataMy.txt"));String str=null;while((str=bis.readLine())!=null){String[] arrStr = str.split(" ");int[] arrInt = new int[arrStr.length];for(int i=0;i<arrStr.length;i++){// 转为 整形arrInt[i] = Integer.parseInt(arrStr[i]);// 如果是 小于 max_each_scan setif(arrInt[i]<max_each_scan){bs.set(arrInt[i],true);}}}String path = "/home/administrator/workspace/HelloWorld/dataoutputMy.txt";File f = new File(path);BufferedWriter bw = new BufferedWriter(new FileWriter(f));for(int i=0;i < max_each_scan;i++){if(bs.get(i)){System.out.print(i+" ");bw.write(i+" ");}}bs.clear();bw.flush();bis.close();bis = new BufferedReader(new FileReader("dataMy.txt"));while((str=bis.readLine())!=null){String[] arrStr = str.split(" ");int[] arrInt = new int[arrStr.length];for(int i=0;i<arrStr.length;i++){arrInt[i] = Integer.parseInt(arrStr[i]);// 如果是 大于 max_each_scan的整形,if(arrInt[i] >= max_each_scan){bs.set(arrInt[i]-max_each_scan,true);}}}System.out.println();for(int i=0;i < max_each_scan;i++){if(bs.get(i)){System.out.print(i+max_each_scan+" ");bw.write(i+max_each_scan+" ");}}// 原来本来一直都忘记 flush或者close来刷新缓冲区bw.flush();bw.close();}}在对于io的各种不认识情况下,算是了解和写好了代码。
今日学习,毕。
下面研究如何用java生成1000W不重复的数据量
由于是从C++的程序中改过来的,所以先要了解一些C++的method以及它们在java中的实现
C++中rand srand的用法
rand()在每次运行的时候都是和上一次相同,srand就是用来更改rand的随机数种子。
JAVA获取随机数
package javaio;import java.util.Random;public class javarandom {/** * @param args */public static void main(String[] args) {// 下面程序是获得指定范围内的重复随机数int[] intRet = new int[6]; int intRd = 0; //存放随机数int count = 0; //记录生成的随机数个数int flag = 0; //是否已经生成过标志while(count<6){// 每次的种子都不一样,这个好像没必要,本来就不一样Random rdm = new Random(System.currentTimeMillis());// 获得一个指定范围的随机数,1到6的随机数intRd = Math.abs(rdm.nextInt())%6+1;//第一次不会执行for(int i=0;i<count;i++){// 从第二次开始,如果生成了重复的随机数目// flag == 1 ,抛弃这个随机数,再生成一个,直到生成足够的随机数if(intRet[i]==intRd){flag = 1;break;}else{flag = 0;}}// 第一次执行后 count == 1 if(flag==0){intRet[count] = intRd;count++;}}// 显示所有随机数for(int t=0;t<6;t++){System.out.println(t+"->"+intRet[t]);}}}
以下是写入文件中的 一定范围内的不重复随机数的生成程序
package javaio;import java.io.BufferedWriter;import java.io.FileWriter;import java.util.Random;public class javarandom {/** * @param args */public static void main(String[] args) throws Exception{final int size = 1000;// 下面程序是获得指定范围内的重复随机数int[] intRet = new int[size]; int intRd = 0; //存放随机数int count = 0; //记录生成的随机数个数int flag = 0; //是否已经生成过标志while(count<size){// 每次的种子都不一样,这个好像没必要,本来就不一样Random rdm = new Random(System.currentTimeMillis());// 获得一个指定范围的随机数,1到6的随机数intRd = Math.abs(rdm.nextInt())%size+1;//第一次不会执行for(int i=0;i<count;i++){// 从第二次开始,如果生成了重复的随机数目// flag == 1 ,抛弃这个随机数,再生成一个,直到生成足够的随机数if(intRet[i]==intRd){flag = 1;break;}else{flag = 0;}}// 第一次执行后 count == 1 if(flag==0){intRet[count] = intRd;count++;}}// 显示所有随机数//for(int t=0;t<size;t++){//System.out.println(t+"->"+intRet[t]);//}BufferedWriter bs = new BufferedWriter(new FileWriter("dataRandom.txt"));// 写入文件中for(int t=0;t<size;t++){bs.write(intRet[t]+" ");if(t%100 == 0 && t!=0){bs.write("\n");}//System.out.println(t+"->"+intRet[t]);}bs.close();}}
接下来就进行 多路归并
多路归并与一般归并的区别,一般归并是2路归并,多路归并是k路归并
归并的有序表有两个,叫做二路归并,归并的有序表有k个,称为k路归并
归并的算法分析:
1. 稳定性: 归并排序是一种稳定的排序。
2. 存储结构要求:可以顺序,也可以链表
3. 时间复杂度:无论是最好还是最环都是O(nlgn)
4. 空间复杂度:O(n) 不是就地排序
注意:若是用单链表做存储结构,很容易给出就地的归并排序
在链表排序中,归并排序很受欢迎,在基于比较的排序法中,时间复杂度为0(nlgn)的排序算法中唯一稳定的排序
多路归并的C++实现转为Java实现,开始:
对Java IO不熟悉,这段代码无法写出,惭愧。
总结:
位图和多路归并两种方案的时空间复杂度比较:
时间空间位图O(N)0.625M多路归并O(Nlogn)1M
多路归并的时间还要加上读写磁盘的时间,以上只是简化的时间复杂度
由于位图只能对只出现一次的特殊情况,所以虽然多路归并败者树比较浪费时间,但是当数据有重复的时候还是有用。程序是写不出了,可以看看败者树,熟悉理论。
bit-map的适用范围:
数据的快速查找,判重(这个相当重要,因为bit-map的不重复特性导致,去重复还可以选用hash),删除。
本章学习,毕,留下任务:多路归并理论,败者树。
- 如何给大数据量的磁盘文件排序
- 【参考】给大数据量的磁盘文件排序
- 如何给10^7个数据量的磁盘文件排序
- 如何给10^7个数据量的磁盘文件排序
- 如何给10^7个数据量的磁盘文件排序
- 如何给10^7个数据量的磁盘文件排序
- 如何给10^7个数据量的磁盘文件排序
- 如何给10^7个数据量的磁盘文件排序
- 如何给10^7个数据量的磁盘文件排序
- 如何给10^7个数据量的磁盘文件排序
- 如何给10^7个数据量的磁盘文件排序
- 程序员编程艺术:第十章、如何给10^7个数据量的磁盘文件排序
- 程序员编程艺术:第十章、如何给10^7个数据量的磁盘文件排序
- 程序员编程艺术:第十章、如何给10^7个数据量的磁盘文件排序
- 程序员编程艺术:第十章、如何给10^7个数据量的磁盘文件排序
- 程序员编程艺术:第十章、如何给10^7个数据量的磁盘文件排序
- 编程珠玑-如何给10^7个数据量的磁盘文件排序
- 编程珠玑-如何给10^7个数据量的磁盘文件排序
- 小波变换和motion信号处理1
- NOJ1079——111…——数论mod
- 最长公共子序列(LCS)
- js模版引擎handlebars.js实用教程——由于if功力不足引出的Helper
- NOJ1080悄悄话游戏
- 如何给大数据量的磁盘文件排序
- 关于c++中的virtual继承的总结
- android中wifi原理及流程分析(很经典)
- In App Purchase总结
- Kinect 3D建模
- c笔记——可变长参数函数用法
- EF框架调用存储过程
- C++基础知识(三) 面向对象
- 关于showmodaldialog 打开新窗口后提交表单操作时,避免弹出新窗口和避免从后台获取“新数据”后不能刷新当前模态页面的解决方案