【问题】
??? 对一百万个不相同的数字进行排序,要求时间复杂度O(1),空间复杂度尽可能小!
【分析】
??? 大数据的排序问题,首选方法是“归并”,之前我也写过十亿个数的归并排序算法,且在此基础上的优化方案——大范围内归并小范围内插入排序等等,但本文有一个时间复杂度的要求,归并排序的时间复杂度是O(nlgn),因此我们尝试一种新闻排序算法——“bit排序法”。
??? “bit排序法”——待排序的数作为bit位的下标,当前位置的bit置为1,一轮遍历待排序数之后,打印出所有当前数值为1的数字下标。
??? 最小的数据结构单位是byte,因此处理起来稍微麻烦了一点
【代码】
package com.hhf; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; /** * bit排序法 * @author HHF * 2015年11月17日17:12:37 * @version 1.0 只支持不同数据的排序 */ public class PhoneNumSort { private static String path = "E:/phoneNum.txt"; private static String resultPath = "E:/phoneNumResult.txt"; private int size = 1000000; public static void main(String[] args) { PhoneNumSort phoneNumSort = new PhoneNumSort(); //生成不相同的一百万个数 phoneNumSort.createNumber(phoneNumSort.size); //统计排序数大小 int bitSize = phoneNumSort.countLineSize(path); //用来保存数据--数组的下标为n,表示数据为8*(n-1)+k byte[] byteData = new byte[bitSize/8 + 1]; phoneNumSort.setByteData(byteData); } /** * 读取文件,并将文件中数值对应到byte类型的打他中去 * @param byteData */ private void setByteData(byte[] byteData){ int index = 0; int n = 0;//第几行 int k = 0;//第几位 try { BufferedReader br = new BufferedReader(new FileReader(path)); String str = br.readLine(); while(str!=null){ index = new Integer(str);//bit中的下标 n = index/8; k = index%8; //设置当前位置的值为1 byteData[n] += getAddNum(k); str = br.readLine(); } br.close(); StringBuffer content = new StringBuffer(); for(int i=byteData.length-1; i>-1; i--){ if(byteData[i]>=128){ byteData[i] -= 128; content.append(8*i + 8).append("\n"); } if(byteData[i]>=64){ byteData[i] -= 64; content.append(8*i + 7).append("\n"); } if(byteData[i]>=32){ byteData[i] -= 32; content.append(8*i + 6).append("\n"); } if(byteData[i]>=16){ byteData[i] -= 16; content.append(8*i + 5).append("\n"); } if(byteData[i]>=8){ byteData[i] -= 8; content.append(8*i + 4).append("\n"); }if(byteData[i]>=4){ byteData[i] -= 4; content.append(8*i + 3).append("\n"); } if(byteData[i]>=2){ byteData[i] -= 2; content.append(8*i + 2).append("\n"); } if(byteData[i]>=1){ content.append(8*i + 1).append("\n"); } } storeDataToFile(resultPath, content.toString().getBytes()); System.out.println(System.currentTimeMillis()+"--排序结果已经写入文件"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } /** * 获得每个位置上对应应该要加的数值 * @param pos 位置 * @return 返回该位置对应的数 */ private int getAddNum(int pos){ if(pos>0 && pos<9){ return 1<<(pos-1); }else{ return 0; } } /** * 读取文章的行数 * @param path 文件路径 * @return size 数据量 */ private int countLineSize(String path){ int count = 0; try { BufferedReader br = new BufferedReader(new FileReader(path)); String str = br.readLine(); while(str!=null){ count++; str = br.readLine(); } br.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis()+"--待排序的数据量是"+count); return count; } /** * 生成指定数量的数据 * @param path 文件的路径 * @param size 数据数量 */ private void createNumber(int size){//还是需要先 定义InputStream输入流对象 if(size < 1){ return; } StringBuffer content = new StringBuffer(); for(int i=1; i<=size; i++){ content.append(i).append("\n"); } storeDataToFile(path, content.toString().getBytes()); System.out.println(System.currentTimeMillis()+"--文件创建结束 共生成了数据 "+size+" 条"); } /** * 将数据存储到文件中 * @param path * @param content */ private void storeDataToFile(String path, byte[] content){ File file = new File(path); if(!file.exists()){ try { file.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } try { java.io.OutputStream os = new java.io.FileOutputStream(path); java.io.BufferedOutputStream bos = new java.io.BufferedOutputStream(os); bos.write(content); bos.flush();// 将缓冲区中的内容强制全部写入到文件中(不管是否已经全部写入)有点类似于下面的语句 bos.close(); os.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
?
--------相关推荐文章---------?
《10亿个字符串的排序问题》http://java--hhf.iteye.com/admin/blogs/2166129
《大范围归并小范围插入排序》http://java--hhf.iteye.com/admin/blogs/2163465
原文:http://java--hhf.iteye.com/blog/2257398