byte用於數字排序

【問題】
    對一百萬個不相同的數字進行排序,要求時間複雜度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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章