日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

10亿个字符串的排序问题

發布時間:2023/12/13 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 10亿个字符串的排序问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、問題描述

有一個大文件,里面有十億個字符串,亂序的,要求將這些字符串以字典的順序排好序

?

二、解決思路

? ? 將大文件切割成小文件,每個小文件內歸并排序;

? ? 對所有的小文件進行歸并排序——多重歸并排序

?

三、解決方案

3.1?模擬產生10億個隨機字符

public static void generateDate() throws IOException {BufferedWriter writer = new BufferedWriter(new FileWriter(ORIGINALPATH));Random random = new Random();StringBuffer buffer = new StringBuffer("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");int range = buffer.length();int length = 1;for (int i = 0; i < BIGDATALENGTH; i++) {StringBuffer sb = new StringBuffer();length = random.nextInt(20)+1;//System.out.println("length--->"+length);for (int j = 0; j < length; j++) {//System.out.println("j--->"+j);sb.append(buffer.charAt(random.nextInt(range)));}System.out.println("sb---->"+sb);writer.write(sb.toString() + " ");}writer.close(); }

?

3.2?對大文件進行切割

/**

}

/*** 將原始數據分成幾塊 并排序 再保存到臨時文件* @throws IOException*/ public static void splitData() throws IOException {@SuppressWarnings("resource")BufferedReader br = new BufferedReader(new FileReader(ORIGINALPATH));tempFiles = new File[BIGDATALENGTH / TEMPFILELENGTH];//將會產生的臨時文件列表for (int i = 0; i < tempFiles.length; i++) {tempFiles[i] = new File(TEMPFILEPATH + "TempFile" + i + ".txt");BufferedWriter writer = new BufferedWriter(new FileWriter(tempFiles[i]));HashMap<Integer,String> hashMap = new HashMap<Integer,String>();//未排序//每次讀出TEMPFILELENGTH個文件 保存到smallLine中for (int j = 1; j <= TEMPFILELENGTH; j++) {String text = null;if ((text = br.readLine()) != null) {hashMap.put(j, text);}}hashMap = MergeSort.sort(hashMap);for(int k=1; k<=TEMPFILELENGTH; k++){writer.write(String.valueOf(hashMap.get(k))+ System.getProperty("line.separator")); //System.getProperty("line.separator")相當于}writer.close();} }

?

3.3?對小文件進行遞歸歸并

?

/*** 多路歸并排序* @param files* @throws IOException*/ public static void multiWaysMergeSort(String[] files) throws IOException {System.out.println("歸并文件-----第 "+mergeSortCount+" 次-----");//當最后只有一個文件的時候 數據已經排序成功 直接復制保存到結果文件if (files.length == 1) {String lastFilePath = LASTFILEPATH + LASTFILENAME;copyFile(files[0], lastFilePath, false);//deleteFile(files[0]);return;}for (int i = 0; i < files.length; i+=2) { //開始合并兩個相鄰的文件 所以一次跳兩個if (i == files.length - 1) { //這時候已經只剩下最后一個文件了 不需要合并 本趟歸并結束renameFile(files[i], i);break;}//將br1 和 br2 寫入到WriteBufferedReader br1 = new BufferedReader(new FileReader(files[i]));BufferedReader br2 = new BufferedReader(new FileReader(files[i + 1]));BufferedWriter writer = new BufferedWriter(new FileWriter(TEMPFILEPATH + "last_" + mergeSortCount + "_" + i + ".txt"));String s1 = br1.readLine();String s2 = br2.readLine();while (s1 != null || s2 != null) {if (s1 != null && s2 != null) { //都不為空 才有比較的必要int mergeResult = s1.compareTo(s2);if (mergeResult > 0) {//s1在s2后面writer.write(s2);writer.write(System.getProperty("line.separator"));s2 = br2.readLine();}if (mergeResult == 0) {//s1=s2writer.write(s1); writer.write(System.getProperty("line.separator"));writer.write(s2); writer.write(System.getProperty("line.separator")); // System.out.println("write time : " + writeTime++);s1 = br1.readLine();s2 = br2.readLine();}if (mergeResult < 0) {//s1在s2前面writer.write(s1); writer.write(System.getProperty("line.separator"));s1 = br1.readLine();}}if (s1 == null && s2 != null) {writer.write(s2);writer.write(System.getProperty("line.separator"));s2 = br2.readLine();}if (s2 == null && s1 != null) {writer.write(s1);writer.write(System.getProperty("line.separator"));s1 = br1.readLine();}}br1.close();br2.close(); // deleteFile(files[i]); // deleteFile(files[i + 1]);writer.close();}mergeSortCount++;multiWaysMergeSort(getTempFiles("last_" + (mergeSortCount-1) + "_")); }

?

3.4?運行結果分析

①生成10億個隨機字符串,時間太久了,,字符串長度隨機在[1,20]之間時,文件大小大概在10.7?GB?(11,500,161,591?字節)

②?切割成小文件,小文件內歸并排序,每個文件內的數據100萬條時,隨機選取五個排序時間如下:

一共發生了410832612?次對比一共發生了?899862656?次交換執行時間為3545毫秒

一共發生了429506513?次對比一共發生了?940765504?次交換執行時間為3512毫秒

一共發生了448181315?次對比一共發生了?981668352?次交換執行時間為3497毫秒

一共發生了466856137?次對比一共發生了?1022571200?次交換執行時間為3497毫秒

一共發生了485530473?次對比一共發生了?1063474048?次交換執行時間為3981毫秒

總共1000個文件切割耗時為

切割小文件所用時間--->4341734ms--->4341.734s--->72.36m--->1.206h

③??小文件遞歸歸并,1000個文件,

共發生了10次歸并,

產生臨時文件總共1999個,

總大小為127.8?GB?(137,201,789,278?字節),

產生結果文件11.6?GB?(12,500,161,591?字節)

比源文件多了10億個字節......

總耗時為--->7374129ms--->7374.129s--->122.9m--->2.048h

不得不提的是,最后執行結果成功,也不枉我苦苦等待

四、相關技術

4.1?歸并排序

排序原理不多介紹,各種到處都有,如果一時不記得,看下面的原理圖。秒懂。


??

4.2?文件讀寫

本程序很重要的一點就是對于文件的讀寫,Buffer的文件讀寫可以很大程度的改善速率

寫操作:

BufferedWriter?writer?=?new?BufferedWriter(new?FileWriter(PATH));

writer.write("hhf ");

讀操作:

BufferedReader?br?=?new?BufferedReader(new?FileReader(PATH));

text?=?br.readLine()

?

五、關于優化

5.1分小文件時優化

前提:數據均勻,保證每個小文件大小不會超過內存的容量

處理:在分數據到小文件時,按字符串按首字母將其分到指定文件中,如A-C分配到1.txt,D-F分配到2.txt.......

優點:只需要小文件內數據排序,排序號后,即可將1.txt、2.txt、3.txt直接連接起來,極大的縮短了歸并時間,相當于把遞歸歸并變成了文件連接而已

缺點:前提不是很容易把握,若有一個小文件內的數據量大于內存的大小,則排序失敗,存在一定的風險

5.2小文件內排序時優化

前提:保證每個小文件內數據量比較不是特別的大

處理:將小文件內的數據進行快速排序

優點:快排的時間效率是高于歸并的

以下是測試數據

排序數量級??101000100000

歸并排序7ms71ms3331ms

快速排序6ms52msjava.lang.StackOverflowError

缺點:缺點已經顯示在測試數據內了,小文件內的數據量過大就可能導致當前線程的棧滿



原文鏈接

更多文章

轉載于:https://www.cnblogs.com/gyjWEB/p/5035763.html

總結

以上是生活随笔為你收集整理的10亿个字符串的排序问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。