column 1由乙個問題展開討論:如何給乙個包含0到9,999,999編號的記錄檔案排序並輸出到另乙個檔案,其中編號不重複,只允許1m左右的記憶體空間。
最優的解法自然是採用位陣列,1.25×106b大小的位陣列含10,000,000位,可以儲存規定範圍內數是否存在。這種方法很好的利用了編號不重複的特性。
要對演算法進行實現,面臨的第乙個問題就是,如何生成這麼乙個記錄檔案?這也練習4提出的問題:如何從範圍0到n-1範圍內生成k個不重複的隨機數。以下是我的乙個解法(column 12對這個問題有詳細的分析並提出了一些解法):
首先生成乙個大小為n的整型陣列,從第0位到第n-1位陣列內容分別填對應的陣列下標,這樣陣列就包含了不重複的從0到n-1的所有數字。那麼接下來的工作就是每次從該陣列未被選擇的數中隨機選擇出乙個數直到選出k個數。對此我們可以將每次選出的數和當前剩餘的未選出的數的最後乙個交換,這樣選擇結束後陣列的最後k個數就是我們「生成」的隨機數。以下是生成隨機數檔案的程式**
使用這個程式後生成了乙個隨機數檔案,發現生成的檔案明顯不隨機!檔案開始的一些數字很小,但是之後的數字幾乎全部集中在9,000,000之上!這顯然是存在問題的。試著減小了maxn和selectk的規模到1000和100,就很正常了。查了一下rand()函式的說明,生成的偽隨機數的範圍是在0到rand_max之間,我的第一感覺就是肯定rand_max偏小!在程式中加入了列印rand_max的語句後,可以看到rand_max的值為32767。看來我的猜測是正確的。所以需要修改程式增大隨機數生成範圍,最簡單的辦法就是rand()生成的隨機數再平方作為最終的隨機數。所以上述**進行以下修改
再次進行測試,發現這次生成的結果就比較正常了。這樣,有了ranfile.txt檔案,就可以接下來進行排序演算法實現了。
c++提供了bit vector的模板類bitset,我們可以很方便的像使用普通陣列那用利用bitset而不必關心位操作的細節。當然也可以自己實現位陣列,書中也進行了一些討論並給出了示例。實現的**如下
bitset模板的預設是全部被初始化為0的。注意的是我在這裡給位賦值的時候並沒有用true或者false,因為true的定義不一定是1,有可能是除0以外的某個整數,所以使用0和1可以保證最大的相容性。
還有乙個問題是大變數的定義,我們應該盡量不定義在棧上而是全域性變數區或者堆上,這樣可以避免棧溢位。雖然這種情況在使用者空間的應用程式中幾乎不可能發生因為應用程式的堆是可以動態增長的,但放在棧資源緊缺的核心空間下,這樣的做法就顯得危險了。所以沒有必要我認為還是不要在棧上定義大變數。
問題5:在解決這個問題時我們使用的實際記憶體是1.25m。如果記憶體的限制不是粗略的1m而是精確的,那麼怎麼解決呢?
這個問題可以結合書中之前給出的解法綜合一下解決。我們可以將給出的大檔案先分成兩份,乙份只含有0-4,999,999而另乙份只含5,000,000-9,999,999。這樣按照之前的方法進行兩次排序,最後將兩個排序結果檔案合併。這樣的話我們和之前相比多出了若干次檔案操作,檔案操作相對記憶體操作是要費時很多的,所以我們應儘量減少檔案操作,可以兩次讀取ranfile.txt檔案,一次只處理0-4,999,999將結果寫入輸出檔案,然後再次讀取ranfile.txt並只處理5,000,000-9,999,999並將結果繼續寫入輸出檔案。這樣我們就只多進行了一次檔案讀取操作,加上檔案系統的快取策略,這種方法的效率和1.25m記憶體的解法差不了太多。
問題6:如果每個數不是最多出現一次,而是最多10次,那麼該怎麼解決呢?
我們可以對這個bitset進行改進,沒個單元不是1位,而是4位,每一單元儲存這個數出現的次數,問題就得到解決了。當然,如果空間還是1m限制的話,呵呵,參見問題5~
程式設計珠璣筆記1
乙個檔案裡有1千萬 10000000 個7位的整數 小於1千萬 給大約1m記憶體讓排序 向量旋轉 abcdefgh 長度n為8 向左旋轉i 3次 某檔案包含40億個隨機次序32位整數,其中有乙個整數未出現,找出來。限制 記憶體幾百位元組,若干順序檔案。乙個詞典有230000個單詞,file和life...
《程式設計珠璣》閱讀筆記1
第一章 磁碟排序 對於乙個提出的問題,不要未經思考就直接給出答案。要先深入研究問題,搞清楚這個問題的特點,根據這個特點,可能有更好的解決方案。比如 文中 最初的需求只是 我如何對磁碟檔案排序 我們首先想到了經典的歸併排序。但進一步了解到排序的內容是10000000個記錄,每條記錄都是乙個7位整數,且...
程式設計珠璣 續(程式設計珠璣 修訂版)
經久不衰的電腦科學名著 集深邃思想 實戰技術與趣味軼事於一冊 領略電腦科學之美 程式設計珠璣 續 作譯者介紹 譯者 錢麗豔 劉田叢書名 圖靈程式設計叢書 出版社 人民郵電出版社 isbn 9787115251510出版日期 2011 年5月 程式設計珠璣 續 是電腦科學方面的經典名著 程式設計珠璣 ...