生活随笔
收集整理的這篇文章主要介紹了
                                
公司的一道考试题算法分析——大数据量整数排序
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.                        
 
                                
                            
                            
                            題目大意:移動公司需要對已經發放的所有139段的號碼進行統計排序,已經發放的139號碼段的文件都存放在一個文本文件中(原題是放在兩個文件中),一個號碼一行,現在需要將文件里的所有號碼進行排序,并寫入到一個新的文件中;號碼可能會有很多,最多可能有一億個不同的號碼(所有的139段號碼),存入文本文件中大概要占1.2G的空間;jvm最大的內存在300以內,程序要考慮程序的可執行性及效率;只能使用Java標準庫,不得使用第三方工具。?
 ??? 這是個典型的大數據量的排序算法問題,首先要考慮空間問題,一下把1.2G的數據讀入內存是不太可能的,就算把1一億條數據,轉都轉換成int類型存儲也要占接近400M的空間。當時做個題目我并沒有想太多的執行效率問題,主要就考慮了空間,而且習慣性的想到合并排序,基本思想是原文件分割成若干個小文件并排序,再將排序好的小文件合并得到最后結果,算法大概如下:?
 
 ??? 1.順序讀取存放號碼文件的中所有號碼,并取139之后的八位轉換為int類型;每讀取號碼數滿一百萬個(這個數據可配置)將已經讀取的號碼排序并存入新建的臨時文件。?
 ??? 2.將所有生成的號碼有序的臨時文件合并存入結果文件。?
 
 ??? 這個算法雖然解決了空間問題,但是運行效率極低,由于IO讀寫操作太多,加上步驟1中的排序的算法(快速排序)本來效率就不高(對于電話排序這種特殊情況來說),導致1億條數據排序運行3個小時才有結果。?
 
 ??? 如果和能夠減少排序的時間呢?首當其沖的減少IO操作,另外如果能夠有更加好排序算法也行。前天無聊再看這個題目時突然想到大三時看《編程珠璣》時上面也有個問題的需求這個這個題目差不多,記得好像使用是位向量(實際上就是一個bit數組),用電話作為index,心中大喜,找到了解決此問題的最完美方案啦:用位向量存儲電話號碼,一個號碼占一個bit,一億個電話號碼也只需要大概12M的空間;算法大概如下:?
 ????? 1.初始化bits[capacity];?
 ????? 2.順序所有讀入電話號碼,并轉換為int類型,修改位向量值:bits[phoneNum]=1;?
 ????? 3.遍歷bits數組,如果bits[index]=1,轉換index為電話號碼輸出。?
 ??? Java中沒有bit類型,一個boolean值占空間為1byte(感興趣的可以自己寫程序驗證),我自己寫個個用int模擬bit數組的類,代碼如下:?
 ???
 
  Java代碼??  
 public?class?BitArray?{?? ????private?int[]?bits?=?null;?? ????private?int?length;?? ?????? ????private?final?static?int[]?bitValue?=?{?? ????????0x80000000,?? ????????0x40000000,?? ????????0x20000000,?? ????????0x10000000,?? ????????0x08000000,?? ????????0x04000000,?? ????????0x02000000,?? ????????0x01000000,?? ????????0x00800000,?? ????????0x00400000,?? ????????0x00200000,?? ????????0x00100000,?? ????????0x00080000,?? ????????0x00040000,?? ????????0x00020000,?? ????????0x00010000,?? ????????0x00008000,?? ????????0x00004000,?? ????????0x00002000,?? ????????0x00001000,?? ????????0x00000800,?? ????????0x00000400,?? ????????0x00000200,?? ????????0x00000100,?? ????????0x00000080,?? ????????0x00000040,?? ????????0x00000020,?? ????????0x00000010,?? ????????0x00000008,?? ????????0x00000004,?? ????????0x00000002,?? ????????0x00000001??? ????};?? ????public?BitArray(int?length)?{?? ????????if(length?<?0){?? ????????????throw?new?IllegalArgumentException("length必須大于零!");?? ????????}?? ????????bits?=?new?int[length?/?32?+?(length?%?32?>?0???1?:?0)];?? ????????this.length?=?length;?? ????}?? ?????? ????public?int?getBit(int?index){?? ????????if(index?<0?||?index?>?length){?? ????????????throw?new?IllegalArgumentException("length必須大于零小于"?+?length);?? ????????}?? ????????int?intData?=?bits[index/32];?? ????????return?(intData?&?bitValue[index%32])?>>>?(32?-?index%32?-1);?? ????}?? ?????? ????public?void?setBit(int?index,int?value){?? ????????if(index?<0?||?index?>?length){?? ????????????throw?new?IllegalArgumentException("length必須大于零小于"?+?length);?? ????????}????????? ????????if(value!=1&&value!=0){?? ????????????throw?new?IllegalArgumentException("value必須為0或者1");?? ????????}?? ????????int?intData?=?bits[index/32];?? ????????if(value?==?1){?? ????????????bits[index/32]?=?intData?|?bitValue[index%32];?? ????????}else{?? ????????????bits[index/32]?=?intData?&?~bitValue[index%32];?? ????????}?? ????}?? ????public?int?getLength(){?? ????????return?length;?? ????}????? }?????? ?????? 
 
 
????
 
??? bit數組有了,剩下就是算法代碼,核心代碼如下:?
 
??? 
  Java代碼??  
 bitArray?=?new?BitArray(100000000);??? ?? while((phoneNum?=?bufferedReader.readLine())!=null){?? ????phoneNum?=?phoneNum.trim().substring(3);?? ?????? ????phoneNumAsInt?=?Integer.valueOf(phoneNum);?? ?????? ????bitArray.setBit(phoneNumAsInt,?1);?? }????? ?? for(int?i?=?0;i<sortUnit;i++){?? ????if(bitArray.getBit(i)==1){?? ????????????writer.write("139"?+?leftPad(String.valueOf(i?+?sortUnit*times),?8));?? ????????????writer.newLine();????????????????????????? ????}????????????????? }?? writer.flush();?? ??? 
 
 
??? 經測試,修改后的算法排序時只需要20多M的內存,一億條電話號碼排序只要10分鐘(時間主要花在IO上),看來效果還是很明顯的。?
 
??? 這個算法很快,不過也有他的局限性:?
 
??? 1.只能用于整數的排序,或者可以準確映射到正整數(對象不同對應的正整數也不相同)的數據的排序。?
 
??? 2.不能處理重復的數據,重復的數據排序后只有一條(如果有這種需求可以在這個算法的基礎上修改,
給出現次數大于1的數據添加個計數器
,然后存入Map中)?
 
??? 3.對于數據量極其大的數據處理可能還是比較占用空間,
這種情況可配合多通道排序算法解決。
?
 
 
??? PS:這個算法的思想源于《編程珠璣》,有興趣的可以讀讀那本書,非常不錯!
 
 
來源:http://pisces-java.iteye.com/blog/766745
                            總結
                            
                                以上是生活随笔為你收集整理的公司的一道考试题算法分析——大数据量整数排序的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。