例如:假設要對8億個正整數進行排序(000000000-999999999),該如何操作?
分析:首先,確認這些數是不是不重複的,這點很重要,8億個9整數佔用內存很龐大,用計算機直接一次性進行處理顯然不現實,800,000,000*4Byte=3.0G。爲此可以利用Bloom Filter建立N個哈希函數的映射集;或者使用導入數據庫的方法;還可以使用bit位的方法......
1、分段排序
由於這8億個數是在數據段000000000-999999999內的,因此可能的數一共有10億個,3.8G空間完全可以足夠,爲此可以將該數據段分爲000000000-099999999、100000000-199999999、......、900000000-999999999共10段,對8億個整數依次搜索位於每一段的數並提取到內存進行排序,然後輸出,每段爲372M,完全在Win32的處理能力內,如是進行10次,並將結果連接起來即可。
由於分段的原因,導致要對許多數字進行多次搜索,例如,如果按分段從前往後的順序依次搜索讀入內存的話,位於最後一段內(即900000000-999999999)的數要被搜索10次,往前依次類推,因此如果該數均勻分佈的話,平均要被搜索5.5次,嚴重影響速度和效率。
2、導入數據庫
可以利用現成的數據庫進行數據的導入,並進行排序,該方法操作簡單,但是要用到數據庫設備,成本增加。
3、bit位方法
由於這8億個數位於000000000-999999999範圍內,爲此可以建立一個10位的二進制數組或空間,對應位置的下標分別爲000000000-999999999,則佔用內存約爲120M,完全位於系統處理能力內。爲此,先將10億位全部置爲0,依次讀入8億個數,將該位置的bit值置爲1,直至結束,則得到一個8億位置爲1的10億數組。將該數組中bit位爲1的下標值依次輸出到文件,即得到排序結果。該方法,佔用內存小,讀取次數少,處理速度相對快。
可以將數據文件分別讀入,讀入一段的代碼如下:
- #include <iostream>
- #include <fstream>
- #include <bitset>
- #include <string>
- using namespace std;
- int CountLines(char *filename)//獲取文件的行數
- {
- ifstream ReadFile;
- int n = 0;
- string temp;
- ReadFiles.open(filename.ios::in);//ios::in表示以只讀的方式讀入讀取文件
- if(ReadFile.fail())
- {
- return 0;
- }//if
- else{
- while(getline(ReadFile,temp))
- {
- n++;
- }//while
- return n;
- }//else
- ReadFile.close();
- }//CountLines
- void input(){
- ifstream file;
- int LINES;
- int *tc = new int[LINES];
- bitset <1000000000> address;
- cout<<"請輸入要打開的文件名:"<<endl;
- cin>>filename;
- file.open(filename,ios::in);
- if(file.fail()){
- cout<<"文件不存在!"<<endl;
- file.close();
- cin.get();
- }else{
- LINES=CoutnLines(filename);
- int *tc = new int[LINES];
- int i = 0;
- while(!file.eof()){//讀取數據到數組
- file>>tc[i];
- address.set(tc[i]);
- ++i;
- }
- file.close();
- }
- }
依次將文件讀入後,最後得到結果,一次性輸出:
- ofstream in;
- in.open("result.txt",ios::trunc);//ios::trunc表示在打開文件前將文件清空,不存在則創建之
- size_t m = address.size();
- for(int j = 0;j! = m;++j)
- if(address.test(j))
- in<<j<<"\n";
- in.close();
排序結束!懇請各位大牛小牛各種牛輕拍指正......