下午看完程式設計珠璣第一章,感覺很不錯!如作者所說:閱讀本書乙個提示,不要太快,一次閱讀一章。集中精力思考,解答課後習題。
寫總結就是在剛弄懂的時候,這時候是最恰當的時候,最容易接受。
題目要求:乙個最多含有1000萬個整數的檔案,整數沒有重複,請輸出公升序排列。
(約束):最多1m記憶體,時間10s。
題目很簡單,但是分析的過程很經典。
剛開始想法,排序唄。。可是時間要求10s,記憶體要求1m,以往像嚴蔚敏《資料結構》
課本上最後的外部排序(歸併排序),時間肯定不行。大家注意,這裡主要的限制是1m
記憶體。在tcpl中,作者說:在儲存空間很寶貴的情況下,有可能需要將多個物件儲存在
乙個機器字中。一種常用的方法是使用類似於編譯器符號表的單個二進位制位標誌集合。
最簡潔的方法就是使用乙個char或int物件中的位標誌集合。
所以此題目的解法就不自覺的運用點陣圖來實現。1m=1024kb約等於1000000b。也就
是8000000位。可是題目有10000000個整數,也就是我們要用800萬位來儲存1000萬
的整數。
注意如果記憶體不是嚴格的1m記憶體,我們可以找出200個稀疏位,1位代表1個整數。
可是如果記憶體是嚴格的受限制1m之內,那麼我們就要想別的方法(下文會提到)。
我們使用的資料結構是整型陣列,int a[1+10000000/32],因為int是32位,而除
法又是地板除,所以我們將1000個整數就儲存在int a陣列中。1位代表1個整數,如
果整數在裡面,就把位置1,否則置0(前提是整數無重複,有重複的情況下面討論)
然後演算法邏輯很簡單,先把所有位置清0,設定相應的位,最後檢測輸出整數。
演算法源**(作者源**,非本人所寫):
#include #define bitsperword 32
#define shift 5
#define mask 0x1f
#define n 10000000
//整型陣列儲存1000萬個整數,1個位儲存1個
//每乙個元素是int,是32位
int a[1 + n/bitsperword];
void set(int i)
void clr(int i)
int test(int i)
int main()
補充:上面**裡的位運算,講的有點不太好,其實通俗的講就是:
i>>shift:利用除法,確定是整型陣列哪乙個int.
1<<(i&mask):利用取餘,確定該置位的是哪一位。
現在,特殊情況我們已經解決(1.不准重複 2.記憶體不是嚴格的1m)
那麼我們來解決這兩個一般性問題:
1.如果整數可以重複,那怎麼辦,就像書上說:可以重複10次。原來1位儲存1個數字
但是現在肯定不行,我們還要儲存數量,於是我們在用4位(16次)來儲存數量,這樣我
們就需要用4000萬位來儲存1000萬的整數了。
2.如果記憶體嚴格的1m怎麼辦?我們怎麼來擴充套件記憶體呢?一般的做法就是:既然1次我
們儲存不了,那麼我們可以把1000萬分成2趟來排序,先用5000000個位的儲存空間來
儲存0~4999999之間的整數,第二趟排序5000000~9999999的整數。k趟演算法可以在kn
的時間開銷和n/k的空間開銷完成排序。
至此,已總結結束,寫作是為了更好的思考!好好學習,為找工作而努力!
程式設計珠璣第一章
原文中的問題 如何在1mb的空間裡面對一千萬個整數進行排序?並且每個數都小於1千萬。實際上這個需要1.25mb的記憶體空間。1mb總共有838,8608。所以估計也可以在1mb左右的空間裡面進行排序了。include include define bitsperword 32 define shif...
《程式設計珠璣》第一章筆記
文章從乙個實際的問題開始 乙個 系統,7位數的 號碼,用1mb的記憶體空間將這些 號碼排序。分析 如果將這些 號碼看成int型別的整數,將其讀入記憶體中進行排序,int型別4個位元組,最多有10000000個 號碼,則需要40mb的記憶體空間,遠遠超出題目的要求,但是這10000000個資料有他們的...
程式設計珠璣 第一章解析
問題 輸入 乙個最多包含n個正整數的檔案,每個數都小於n n 1000w 如果在輸入檔案中有任何整數重複出現就是致命錯誤。沒有其他資料與該整數相關聯。輸出 按公升序排列的輸入整數的列表。約束 最多有 大約 1 mb的記憶體空間可用,有充足的磁碟儲存空間可用。執行時間最多幾分鐘,執行時間為10秒就不需...