超大檔案內單詞排序 檔案大小大於記憶體

2021-10-06 10:24:07 字數 1520 閱讀 3539

檔案200g,內部儲存著單詞,單詞之間以逗號分隔,請生成乙個有序檔案,對所有單詞按照字典序排列。限制你使用的用於儲存檔案內容的記憶體大小為1g。

(面試時臨時想了出來,雖然不是最好的方法,但是只要work,面試就算通過!)

先遍歷檔案,將以a頭的單詞找出來,對這些單詞進行排序並儲存,然後找b開頭的單詞,依次類推,最後將各個小檔案組合。如果找的過程中發現以a開頭的單詞太多,則繼續分成以aa開頭,以ab開頭...。

另外,例如,  為了防止以a開頭的單詞過多,可以設定乙個閾值,例如10000個單詞或者1g,當遍歷過程中找到的以a開頭的單詞大於1000個 或者 以a開頭的單詞構成的檔案將會大於1g時,則放棄,轉而,先找以aa開頭的....

針對這種問題有一種經典的方案:外排序。

一般來說,外排序處理的資料不能一次裝入記憶體,只能放在讀寫較慢的外儲存器(通常是硬碟)上。

外排序通常採用的「排序-歸併」的策略。在排序階段,先讀入能放在記憶體中的一定大小的資料量,將其排序輸出到乙個臨時檔案,依此進行,最後得到多個有序的臨時檔案。之後在歸併階段將這些臨時檔案組合為乙個大的有序檔案。

例如,如果限制你所使用的記憶體的大小為1g, 對於20g的檔案進行排序, 則, 每次讀入1g內容,以某種常規方式在記憶體中完成排序(快速排序、堆排序、歸併排序等等),然後,輸出為乙個內部資料有序的臨時檔案存到磁碟。最後對20個有序檔案進行歸併。

歸併時也必須考慮記憶體大小的限制:

讀入每個臨時檔案的前1/(20+1) g的內容到記憶體,之所以20+1, 是因為要預留緩衝區用於存放歸併的結果,相當於將可用記憶體空間分成了21份,其中20份用於儲存從每個臨時檔案中讀入的內容,剩餘的乙份用於儲存中間結果。 (實踐中,將輸入緩衝適當調小,而適當增大輸出緩衝區能獲得更好的效果)。 

note: 根據歸併演算法,歸併排序時必須同時考慮所有的臨時檔案。

執行20路歸併演算法,將結果輸出到輸出緩衝區。一旦輸出緩衝區滿,將緩衝區中的資料寫出至目標檔案,清空緩衝區。一旦20個輸入緩衝區中的乙個變空,就從這個緩衝區關聯的檔案,讀入下乙個1g資料,除非這個檔案已讀完。

這是「外歸併排序」能在主存外完成排序的關鍵步驟 -- 因為「歸併演算法」(merge algorithm)對每乙個大塊只是順序地做一輪訪問(進行歸併),每個大塊檔案不用完全載入主存!

為了增加每乙個有序的臨時檔案的長度,可以採用置換選擇排序(replacement selection sorting)。它可以產生大於記憶體大小的順串。具體方法是在記憶體中使用乙個最小堆進行排序,設該最小堆的大小為m。演算法描述如下:

初始時將輸入檔案讀入記憶體,建立最小堆。

將堆頂元素輸出至輸出緩衝區。然後讀入下乙個記錄:

若該元素的關鍵碼值不小於剛輸出的關鍵碼值,將其作為堆頂元素並調整堆,使之滿足堆的性質;

否則將新元素放入堆底位置,將堆的大小減1。

重複第2步,直至堆大小變為0。

此時乙個順串已經產生。將堆中的所有元素建堆,開始生成下乙個順串。

此方法能生成平均長度為 2m的順串,可以進一步減少訪問外部儲存器的次數,節約時間,提高演算法效率。

ref:

PHP上傳大檔案之前檢查檔案大小方法

1.在客戶端檢查 2.在伺服器檢查 在 php.x.xx php.ini 或 應用程式的 htaccess中配置,這個缺點是上傳操作一旦提交,不可自動撤消直到上傳的檔案大小超出配置值 upload max filesize 100m max file size 100m max execution ...

PHP在上傳大檔案前如何檢查檔案大小

1.在客戶端檢查 post enctype multipart form data action upload.php file name file id file submit name submit value submit form document.forms 0 addeventliste...

linux ls 按照檔案大小排序

一般我們用作在lunux查詢檔案都習慣是ls ltr 按照時間逆序排列 但是有的時候比如為了清理日誌啥的想要按照大小排列一下,清理最大的嘛。所以就需要 ls ls 按照大小排列 從大到小 如果想要從小到大 排列就是ls lsr r就是逆序的意思。還有之前看其他文章說加乙個 h 表示 numan re...