27 电话号码排序

来源:互联网 发布:linux查看进程id 编辑:程序博客网 时间:2024/05/01 00:37

前言

本博文部分图片, 思路来自于剑指offer 或者编程珠玑

这部分来自于编程珠玑, “编程珠玑”就是从这个例子开始的, 我看了过后, 感觉非常有意思啊, 觉得能够冲这本书中学到很多东西
不过 后来看完之后, 又过了几个月, 便基本上快要忘光了…
可能是对于 这本书敲的代码不多吧, 很多问题在前面的几本书中出现过
这本书敲的代码 似乎仅仅4, 5个
而且 部分章节十分注理论的描述, so 忘记了..

问题描述

这里写图片描述

这里写图片描述

思路

思路一 : 使用外部排序, 分批加载到内存排序, 输出, 合并

思路二 : 四十个”线程”[我没有理解到”通道”的含义, 我的理解为线程]对于 四十批数据进行快速排序

思路三 : 输入的数据有两个特性, 第一 : 不重复, 因此 我们不用记录每一个数据的个数, 而只用记录该数字是否存在, 2. 数字固定在一个区间[0 - 9999999] [10000000 / 8 / 1024 / 1024 = 1.19], 根据上述的计算, 使用BitSet的话, 只需要1.19M [似乎 超出了一点啊]的内存就可以表示[0 - 9999999]
读取文件, 获取每一个数字, 将对应的位置为1, 读取完文件中所有的数据之后, 遍历一次BitSet, 输出到目标文件即可

思路二编程珠玑原图
这里写图片描述

参考代码

: 1 代码中只实现了思路三
      2 代码中生成随机数据的时候, 假定不重复, 如果存在重复 忽略

/** * file name : Test25BigFileSort.java * created at : 4:51:26 PM Jun 10, 2015 * created by 970655147 */package com.hx.test05;public class Test25BigFileSort {    // 参数, max 表示生成的数的个数, range 表示生成的数的范围    // space 表示空格    // numPerLine 每一行应该存储的数字的个数    static int MAX = 1000;    static int RANGE = 1000000;    static int CAP_LEFT_MOVE = 4;    static char SPACE = ' ';    static int numPerLine = 1 << 5, lineMask = numPerLine - 1;    // 实现大文件排序    public static void main(String []args) {        String path = System.getProperty("user.dir") + "\\tmp\\Test25BigFileSort.txt";        String tarPath = System.getProperty("user.dir") + "\\tmp\\Test25BigFileSortTar.txt";        try {            generateBigFile(path);//          readFromFile(path);            sortBigFile(path, tarPath);        } catch (IOException e) {            e.printStackTrace();        }//      String str = "7 65417 2699";//      Log.log(getLastSpace(str, 2));    }    // 对大文件的数据进行排序        // 创建一个BitSet[BitMap], 用于保存数据, 是否存在        // 然后读取输入文件, 逐行解析, 并设置响应的位为true        // 最后  将存在的数字, 输出到目标文件, 实现了排序    private static void sortBigFile(String path, String tarPath) throws IOException {        BitSet bs = new BitSet(RANGE);        resolve(path, bs);        Log.log("resolve data success ...");        writeResult(tarPath, bs);        Log.log("write data success ...");    }    // 将文件逐行解析        // 当然 这里一个String.split 会更简单    private static void resolve(String path, BitSet bs) throws NumberFormatException, IOException {        File tarFile = new File(path);        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(tarFile)) );        try {            String line = null;            while((line = br.readLine()) != null ) {                if(line.trim().length() == 0) {                    continue ;                }                int idx = 0;                int first = 0, second = 0;                int idxMax = Tools.getLastSpace(line, 2, SPACE);                while(first < idxMax ) {                    while(line.charAt(idx ++) != SPACE) ;                    second = idx - 1;                    int val = Integer.parseInt(line.substring(first, second) );                    bs.set(val, true);    //              Log.logWithoutLn(val + " ");                    while(line.charAt(idx ++) == SPACE) ;                    first = idx - 1;                }                // 统计最后一个数组                while(line.charAt(idx ++) != SPACE) ;                second = idx - 1;                int val = Integer.parseInt(line.substring(first, second) );                bs.set(val, true);            }        } finally {            if(br != null) {                br.close();            }        }    }    // 将结果输出文件    private static void writeResult(String tarPath, BitSet bs) throws IOException {        File tar = new File(tarPath);        Tools.createNewFile(tar);        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tar) );        StringBuilder sb = new StringBuilder((numPerLine + 2) << CAP_LEFT_MOVE);        int cnt = 0;        try {            for(int i=0; i<bs.size(); i++) {                if(bs.get(i)) {                    if((cnt & lineMask) == lineMask) {                        sb.append("\r\n");                        bos.write(sb.toString().getBytes() );                        sb.setLength(0);                    }                    sb.append(i + " ");                    cnt ++;                }            }            bos.write(sb.toString().getBytes() );        } finally {            if(bos != null) {                bos.close();            }        }    }    // 写出数据[写出MAX个范围为RANGE的随机数到path所在的文件中]    public static void generateBigFile(String path) throws IOException {        File tarFile = new File(path);        Tools.createNewFile(tarFile);        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tarFile) );        try {            Random rand = new Random();            StringBuilder sb = new StringBuilder((numPerLine + 2) << CAP_LEFT_MOVE);            for(int i=0; i<MAX; i++) {                sb.append(rand.nextInt(RANGE) + " ");                if((i & lineMask) == lineMask) {                    sb.append(Tools.CRLF);                    bos.write(sb.toString().getBytes());                    sb.setLength(0);                }            }            bos.write(sb.toString().getBytes() );        } finally {            if(bos != null) {                bos.close();            }        }        Log.log("write data success ...");    }    // 读取path文件中的数据[BufferedReader]    public static void readFromFile(String path) throws IOException {        File tarFile = new File(path);        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(tarFile)) );        try {            String line = null;            while((line = br.readLine()) != null ) {                Log.log(line);            }        } finally {            if(br != null) {                br.close();            }        }    }    // 读取path文件中的数据[FileChannel]    public static void readFromFile02(String path) throws IOException {        File tarFile = new File(path);        FileChannel fc = Tools.getFileChannel(tarFile);        try {            ByteBuffer bBuf = ByteBuffer.allocate((numPerLine + 1) << CAP_LEFT_MOVE);            byte[] buff = new byte[((numPerLine + 1) << CAP_LEFT_MOVE)];            int readed = -1;            while((readed = fc.read(bBuf)) != -1) {                bBuf.flip();                bBuf.get(buff, 0, readed);                Log.log(new String(buff, 0, readed) );            }        } finally {            if(fc != null) {                fc.close();            }        }    }}

Tools. getLastSpace(String str, int n, char tar)

    // 获取倒数第"n个"空格 [连续的相同字符不算]    // 当然这里的鲁棒性存在问题 [while(str.charAt(-- i) == tar) ;]    public static int getLastSpace(String str, int n, char tar) {        int idx = -1;        int cnt = 0;        for(int i=str.length()-1; i>=0; i--) {            if(str.charAt(i) == tar) {                cnt ++;                if(cnt == n) {                    idx = i;                    break ;                }                while(str.charAt(-- i) == tar) ;            }        }        return idx;    }

效果截图

这里写图片描述

总结

大数据的处理 BitSet也是神器之一, 还有前面介绍的BloomFilter, 以及其他的数据结构

注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!

0 0
原创粉丝点击