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, 所以请大家指出!
- 27 电话号码排序
- 编程珠玑: 电话号码排序
- 【编程珠玑】第一章电话号码排序
- 电话号码排序问题——位图排序
- 电话号码
- 电话号码
- 电话号码
- 电话号码
- 电话号码
- 电话号码
- 电话号码
- 电话号码
- 电话号码
- 电话号码
- 电话号码
- 编程珠玑第一章,电话号码排序问题
- java 对电话号码的排序方法
- POJ 1002 电话号码排序查重
- Activity和Service的交互(学习笔记)
- markdown语法(看这张图就够了)
- MATLAB的小技巧
- [2016.01.20]CTEX_DAY1
- 传值与传引用
- 27 电话号码排序
- Android中给LineayLayout加边框
- C#queue队列总结
- CSS之基础知识
- mysql 的表
- javax.el.PropertyNotFoundException: Property 'name' not found on type java.lang.String
- win10清理自带xbox,天气等应用
- 视频播放器
- 【cocos2d-x 2.x 学习与应用总结】12: cocos2d-x预定义shader源码