1. 程式人生 > >【漫畫】什麼是外部排序?(絕對讓你有所收穫)

【漫畫】什麼是外部排序?(絕對讓你有所收穫)

 

背景

西天取經的路上,一樣上演著程式設計的樂趣.....

這篇文章我將通過對話的形式帶大家由淺入深著讀懂外部排序。

 

 

排序的時候我們可以選擇快速排序或歸併排序等演算法。為了方便,我們把排序好的2G有序資料稱之為有序子串吧。接著我們可以把兩個小的有序子串合併成一個大的有序子串。

 

注意:讀取的時候是每次讀取一個int數,通過比較之後在輸出。

 

按照這個方法來回合併,總共經過三次合併之後就可以得到8G的有序子串。

 

 

接下來把12個數據分成4份,然後排序成有序子串

 

 

然後把子串進行兩兩合併

 

 

輸出哪個元素,就在那個元素所在的有序子串再次讀入一個元素

 

 

繼續

 

 

重複直到合併成一個包含6個int的有序子串

 

 

再把兩個包含6個int的有序子串合併成一個包含12個int資料的最終有序子串

 

 

優化策略

 

解釋下:例如對於資料2,我們把無序的12個數據分成有序的4個子串需要讀寫各一次,把2份3個有序子串合併成6個有序子串讀寫各一次;把2份6個有序子串合併從12個有序子串讀寫各一次,一共需要讀寫各3次。

 

 

 

 

多路歸併

 

為了方便講解,我們假設記憶體一共可以裝4個int型資料

 

 

 

 

 

 

 

置換選擇

 

 

 

 

 

 

 

 

例如我們可以從12個數據讀取3個存到記憶體中,然後從記憶體中選出最小的那個數放進子串p1裡;

 

之後再從在從剩餘的9個數據讀取一個放到記憶體中,然後再從記憶體中選出一個數放進子串p1裡,這個數必須滿足比p1中的其他數大,且在記憶體中儘量小

 

這樣一直重複,直到記憶體中的數都比p1中的數小,這時p1子串存放結束,繼續來p2子串的存放。例如(這時假設記憶體只能存放3個int型資料):

 

12個無序的int資料

 

 

讀入3個到記憶體中,且選出一個最小的到子串p1

 

 

從記憶體中再次讀取一個元素86

 

 

從記憶體中再次讀取一個元素3

 

 

從記憶體中再次讀取一個元素24

 

從記憶體中再次讀取一個元素8

 

 

這個時候,已經沒有符合要求的數了,且記憶體已滿,進而用p2子串來存放,以此類推。

 

通過這種方法,p1子串存放了4個數據,而原來的那種方法p1子串只能存放3個數據。

 

 

(不知道堆排序的可以看下我之前寫的文章:【演算法與資料結構】堆排序是什麼鬼?)

 

從12個數據中讀取3個數據,構建成一個最小堆,然後從堆頂選擇一個數寫入到p1中。

 

之後再從剩餘的9個數中讀取一個數,如果這個數比剛才那個寫入到p1中的數大,則把這個數插入到最小堆中,重新調整最小堆結構,然後在堆頂選一個數寫入到p1中。

 

否則,把這個數暫放在一邊,暫時不處理。之後一樣需要調整堆結構,從堆頂選擇一個數寫入到p1中。

 

這裡說明一下,那個被放在一邊的數是不能再放入p1中的了,因為它一定比p1中的數都要小,所以它會放在下一個子串中

 

看這些文字會讓人頭大,我畫圖解釋下吧。

 

從12資料讀取3個數據

 

 

構建最小堆,且選出目標數

 

 

讀入下一個數86

 

 

讀入下一個數3,比70小,暫放一邊,不加入堆結構中

 

 

讀入下一個資料24,比81小,不加入堆結構

 

 

讀入下一個資料8,比86小,不加入堆結構。此時p1已經完成了,把那些剛才暫放一邊的數重新構成一個堆,繼續p2的存放。

 

 

以此類推...

最後生成的p2如下:

 

 

 

 

 

 

這種方法適合要排序的資料太多,以至於記憶體一次性裝載不下。只能通過把資料分幾次的方式來排序,我們也把這種方法稱之為外部排序

 更多高質量漫畫原創文章,大家可以關注我的微信公眾號:苦逼的碼農。文章將第一時刻發表於我的公眾號。

 

本公眾號(苦逼的碼農)專注於寫【Java】、【計算機網路】、【資料結構與演算法】,期待你的關注。