問題:
給定輸入文件,文件中每條記錄是一個整型數(不重複),每條記錄最大爲n,n<=10000000,要求對文件中所有記錄排序(從小到大),然後輸入到給定文件。
限制:主存不超過1MB(實際程序超過了1M)。
按照《編程珠璣》上介紹,有以下幾種方法:
1,多通道分片讀取文件,然後合併排序分片文件
2,位圖排序:適合於對大量不重複數據,並且數據其他相關數據。
位圖排序就是使用一張表來記錄關鍵字的存在狀態(存在或不存在),然後通過採集到的狀態(在/不在)通過一次遍歷來確定序列順序。
算法描述如下:
示例:對於不超過20的整型數據,可以用20個bit位來表示,例如1,2,4,14可表示:
00000010000000001011,即將每一個數對應的bit位置1。
因此,對於10000000個記錄項,可以用10000000個bit位來表示。
在設置或清除每一個讀取的整數對應的位時:
(1)首先找到該整數對應的數組的下標(i>>5)。由於數組中的每一個整數有32位(假設int型爲32位),這32位可以表示32個整數。
(2)找到該整數在對應整數的位座標pos。
(3)設置或清除該整數的位。
1 #include <iostream>
2 #include <bitset>
3 #include <fstream>
4 #include <vector>
5 using namespace std;
6 const int BITSPERWORD=32;
7 const int MAX = 100000;
8 const int NUM = MAX/BITSPERWORD;
9 vector< bitset<32> > vec(1+NUM);
10 void set(int i )
11 {
12 /*
13 int tmp = i>>5;
14 cout << tmp <<endl;
15 */
16 vector<bitset<32> >::iterator it = vec.begin();
17 int pos = i%32;
18 it += i>>5;
19 (*it).set(pos,1);
20 }
21 void clear(int i)
22 {
23 vector<bitset<32> >::iterator it = vec.begin();
24 int pos = i%32;
25 it += i>>5;
26 (*it).reset(pos);
27 }
28 int test(int i)
29 {
30 vector<bitset<32> >::iterator it = vec.begin();
31 int pos = i%32;
32 it += i>>5;
33 if((*it).test(pos))
34 return 1;
35 else
36 return 0;
37
38 }
39 int main()
40 {
41 ifstream fin("source.file");
42 ofstream fout("sort.file");
43 int i = 0;
44 int tmp = 0;
45
46 vector< bitset<32> >::iterator it = vec.begin();
47 while(it!=vec.end())
48 {
49 (*it).reset();
50 //cout << (*it)<<endl;
51 it++;
52 }
53 /*
54 for(i = 0;i<NUM +1;i++)
55 clear(i);
56 */
57 while(fin>>tmp)
58 {
59 set(tmp);
60 }
61 for(i = 0;i<MAX+1;i++)
62 if(test(i))
63 fout<< i << endl;
64 }
c語言實現如下:
1 #include <stdio.h>
2
3 #define MAX 100000
4 #define BITSPERWORD 32
5 #define NUM (MAX/BITSPERWORD)
6
7 int a[NUM+1];
8 void set(i)
9 {
10 int label;
11 int pos;
12 label = i>>5;
13 pos = i%32;
14 // pos = i&0x1f;
15 a[label] |= 1<<pos;
16 }
17 void clear(i)
18 {
19 int label;
20 int pos;
21 label = i>>5;
22 pos = i%32;
23 //pos = i&0x1f;
24 a[label] &= ~(i<<pos);
25 }
26 int test(i)
27 {
28 int label;
29 int pos;
30 label = i>>5;
31 // pos = i&0x1f;
32 pos = i%32;
33
34 if(a[label]&(~(1<<pos)))
35 return 1;
36 else
37 return 0;
38 }
39 int main()
40 {
41
42 FILE *fin;
43 FILE *fout;
44 fin = fopen("source.file","r");
45 fout = fopen("sort.file","w");
46 int i = 0;
47 for(i = 1;i<MAX+1;i++)
48 clear(i-1);
49 int tmp;
50 while(fscanf(fin,"%d",&tmp)!=EOF)
51 {
52 set(tmp-1);
53 }
54 for(i = 1;i<MAX+1;i++)
55 {
56 if(test(i-1))
57 {
58 fprintf(fout,"%d/n",i);
59 }
60 }
61 }
在我的機器上測試兩種語言實現的效率:測試的數據位100000,c++用時爲c語言的約兩倍。
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/zhongjiekangping/archive/2010/04/02/5444083.aspx