1. 程式人生 > >【演算法思想】點陣圖排序演算法

【演算法思想】點陣圖排序演算法

問題的提出

一個最多包含n個正整數的檔案,每個數都小於n,其中n=10^7。假設最多隻有1M的記憶體空間可用,在考慮空間和時間的優化的情況下,請問如何對其進行排序?

常規思想

我們假設這些整數都是用整型儲存(一般整型的大小為4個位元組),那麼1M位元組可以儲存250 000個數據。由於輸入檔案最大可能有10^7個數據,因此可以通過遍歷輸入檔案40次來完成排序。第一次將在[0,249 999]範圍內的整數讀入到記憶體中,第二次將在[250 000,499 999]範圍內的整數讀入到記憶體中,依此類推。每讀入一次資料,就對這些資料進行排序(可以採用一些排序演算法)並輸出。顯然,我們要對檔案進行反覆的讀寫,這不是我們所期望的。下面我們提出一種更加合理的演算法—點陣圖排序演算法

點陣圖排序演算法

如果我們想一次讀取檔案的全部內容(最大可能有1000萬個整數),問題在於如何用1M的記憶體來表示這些數。我們可以用位圖表示集合。我們可以用一個長度為20的字元陣列來表示小於20的所有正整數的集合。舉例說明:下面的字串可以表示集合{1,2,3,5,8,13}: 0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0 集合中有數值的位置都置為1,其它所有位置為0.

這樣我們就用一個具有1000萬個位的字串表示了這個檔案,其中,當且僅當整數i在檔案中存在時,第i位為1。因此我們可以分下面三步來解決這一問題:

  1. 將字串的所有位置為0即初始化
  2. 逐一讀取檔案中的每個整數,並將以該整數為下標的對應為置為1
  3. 逐一檢查字串的每一位,如果為1,則輸出這一元素的下標

時間、空間的折中與雙贏

我們在很多問題中,都遇到著時間和空間的折中,毛澤東在論持久戰中也說過以空間換時間(據說是蔣介石先提出來的)。但是上面的程式是:減少程式空間需求的同時也減少了其執行時間。因為需要處理的資料變少了,從而處理資料所需要的時間變少了,同時沒有反覆的讀取檔案,進一步避免了磁碟的訪問時間。當然,只有當原始設計非最佳方案時,才有可能時空雙贏。

奧卡姆的剃刀

    設計者確定其設計已經達到完美的標準不是不能再新增任何東西,而是不能再減少任何東西。