算是一道常見的面試題引來的,有些大廠也喜歡把這個題當做面試題。
主題:例如有一個 1g 的文件,裡面存放這亂序不唯一的數字,如果利用 100m 完成整體排序?
實作過程就是:
1、先將大檔案逐行讀取,每10000 行為一組,然後排序後寫入檔案中,文件名稱類似t1.txt, t2.txt ... 這樣的名稱,直至讀取和拆分完畢整個文件,
2、然後遍歷所有文件,每個文件先讀取第一行,放入臨時排序數組$tmpNums**,然後取其中最小值,**放入臨時存儲數組$nums,同時記錄當前位置的索引值$idx
3、從最小值所在索引對應檔案中取下一個數字,放入臨時排序數組的當前索引中,然後繼續重複第2 步的操作,直到所有檔案的所有內容都讀取完畢,則整體檔案重新排序完畢。以下是一個PHP 多路歸併排序demo 程式碼,只是簡單的骨架結構,例如min 取最小值部分,可以擴展成定長最小堆實現,或者優先隊列,能保存值和所在文件就行。
PHP 多路歸併demo 代碼:
function multiWaySort() { // 读取所有的文件描述符 $fds = []; $dir = scandir('./runtime/txt/'); foreach ($dir as $file) { if ($file != '.' && $file != '..') { $fds[] = fopen('./runtime/txt/' . $file, 'rb'); } } // 读取每个文件的第一行内容,放入临时排序数组 $tmpNums = []; foreach ($fds as $fd) { $tmpNums[] = (int)fgets($fd); } $nums = []; $count = 0; while (true) { if (empty($tmpNums)) break; // 最小值放入临时存储数组 $value = min($tmpNums); $nums[] = $value; // 读取最小值所在索引,对应的文件下一行内容 $idx = array_search($value, $tmpNums); $next = fgets($fds[$idx]); if (!$next) { unset($tmpNums[$idx]); unset($fds[$idx]); } else { $tmpNums[$idx] = (int)$next; } // 临时存储数组到达一定数量追加写入文件一次 if (count($nums) == 20) { foreach ($nums as $value) { $f = fopen('./runtime/result.txt', 'ab+'); fwrite($f, $value . PHP_EOL); } $nums = []; } if ($count == 4999999) { continue; } $count++; } }
#推薦學習:《PHP影片教學》
詳解K路歸併排序(實戰)》
#《一文了解大檔案排序/外存排序問題》