程式設計珠璣開篇 磁碟檔案排序問題

2021-04-18 00:44:42 字數 1703 閱讀 9109

輸入:

所輸入的檔案,至多包含n個正整數,每個正整數都小於n,題目中n = 10^7,如果輸入時某個正整數重複出現倆次,就會產生致命的錯誤,這些整數,與其他任何資料都不相關.

輸出:以增序形式輸出經過排序的整數列表

約束至多只有1mb(包括程式本身)可用的主存,但是可以用的磁碟空間是充足的,執行時間至多幾分鐘,10秒針是最適宜的執行時間.

作者第乙個方案使用基於磁碟的合併排序.將每個號碼用32位整數表示,可以在1mb的空間裡儲存250000個號碼,使用乙個帶有40個通道的程式,在第乙個通道中將前250000的任意整數讀入記憶體,並對它們進行排序,可以使用高效的快速排序,但是完成整個任務,我們要犧牲讀檔案40次的代價.最後作者引出了另外一種解決方案點陣圖和位向量:

我們可以用乙個20位的字串可以表示小於20的非負數集合.例如,我們可以將集合儲存在下面字串中:

集合中代表數字的各個位設定為1 ,而其他的位全部設定為0

在上面問題中,我們使用一千萬位的字串表示該檔案,當且僅當整數i在該檔案中的時候,第i位才被設定為1,這種表示法使用了這個問題中的三中屬性,輸入的範圍相對小一些,並且還不包括重複的資料,而且沒有資料和單個整數以外的每一記錄相關聯

演算法實現分三階段

1 設定每個位為0

2 讀取檔案,將相應的位設定為1

3 檢查每個位,當為1時,將整數寫入

這些函式使用常量來設定,清除並測試位值

#define bitspereord 32 // the type int contains 32 bits 

#define shift 5 // pow(2,5)

#define mask 0x1f //00011111

#define number 10000000

int bitbuffer[ 1 + number / bitspereord ] ;

void clr( int i ) //set every bit 0

//i & mask 相當於 i mod 32

void set ( int i ) //set the n bits 1  

int test( int i ) //read the sort number from bitbuffer

通過位運算實現的上面的排序演算法如下:

int main () 

while(scanf("%d",&i) != eof )

for ( i = 0 ; i < number ;i ++ )

return 0 ;

}使用乙個包含100萬個不重複正整數的檔案且每個正整數都小於1000萬進行測試:下表報告了使用

系統命令行排序,c++和c的排序程式,位運算的排序成本
系統排序

c++/stl

c/qsort

c/位運算

總時間(秒)

8938

12.6

10.7

計算時間(秒)

7928

2.40.5

mb0.8704

1.25  

程式設計珠璣開篇 磁碟檔案排序問題

輸入 所輸入的檔案,至多包含n個正整數,每個正整數都小於n,題目中n 10 7,如果輸入時某個正整數重複出現倆次,就會產生致命的錯誤,這些整數,與其他任何資料都不相關.輸出 以增序形式輸出經過排序的整數列表 約束至多只有1mb 包括程式本身 可用的主存,但是可以用的磁碟空間是充足的,執行時間至多幾分...

程式設計珠璣開篇 磁碟檔案排序問題

輸入 所輸入的檔案,至多包含n個正整數,每個正整數都小於n,題目中n 10 7,如果輸入時某個正整數重複出現倆次,就會產生致命的錯誤,這些整數,與其他任何資料都不相關.輸出 以增序形式輸出經過排序的整數列表 約束至多只有1mb 包括程式本身 可用的主存,但是可以用的磁碟空間是充足的,執行時間至多幾分...

程式設計珠璣 第一章 開篇

一,題目 如何在1mb的空間裡面對一千萬個整數進行排序?並且每個數都小於1千萬。實際上這個需要1.25mb的記憶體空間 這裡所說的空間是考慮用位圖表示法時,每一位代表乙個數,則1千萬 1024 1024 8 約為1.25mb 1mb總共有838,8608個可用位。所以估計也可以在1mb左右的空間裡面...