如何在有限的記憶體的情況下,找到大量資料中重複查詢次數最多的語句
阿新 • • 發佈:2019-01-08
//500K記憶體,100萬條資料,尋找裡面重複查詢次數最多的記錄 //思想顯示對100萬條資料分在不同的檔案中,但是在分檔案中的時候,要對起進行一定處理,分到對於的檔案中,比如分成100個 //檔案,那麼對每一條string進行hash得到的整數值%100,這樣就分到不同的檔案中了,然後確保其他檔案中沒有這一條記錄, //然後對每一個檔案進行處理,取樣hash值,然後存入相應的檔案中。 //然後對每一個檔案中資料進行快速排序,存入資料,這樣保證資料最大的在前面。 //然後對所有檔案的第一個數,進行排序,這樣就能夠得到最大的那條記錄了。 #include <iostream> #include <fstream>//wenjian #include <string> #include <sstream>//stringstream #include <unordered_map>//undered_map #include <algorithm>//sort() #include <utility>//pair() using namespace std; //產生100萬條資料,隨機。儲存在data.txt中 bool Generate_Data() { ofstream outfile("data.txt"); if(outfile.fail()){ cout<<"Open file failed!"<<endl; return false; } int a = 0; for(int i = 0; i < 1000000; ++i){ a = rand() % 10000; outfile<<a<<endl; } outfile.close(); return true; } inline unsigned int RSHash(string &str) { unsigned int b = 378551; unsigned int a = 63689; unsigned int hash = 0; int i = 0; int size = str.size(); while (i < size) { hash = hash * a + str[i]; a *= b; i++; } return (hash & 0x7FFFFFFF); } //按照這個規則排序快速排序 bool mysort(const pair<string,int> &x, const pair<string,int> &y) { return x.second > y.second; } //對100萬行分別hash,然後根據hash值分50組 bool Split_Into_Groups(string &str) { ifstream infile(str); if(infile.fail()){ cout<<"Open file failed!"<<endl; return false; } ofstream outfile[50]; stringstream ss; string name_num, file_name; for(int i = 0; i < 50; ++i){ ss.clear(); ss<<i; ss>>name_num; file_name = name_num + ".txt"; outfile[i].open(file_name); if(outfile[i].fail()){ cout<<"Open file failed"<<endl; return false; } } string tmp; int hash_val; while(getline(infile,tmp)){ hash_val = RSHash(tmp) % 50; outfile[hash_val]<<tmp<<endl; } infile.close(); for(int i = 0; i < 50; ++i){ ss.clear(); ss<<i; ss>>name_num; file_name = name_num + ".txt"; outfile[i].close(); } //檔案去重; for(int i = 0; i < 50; ++i){ ss.clear(); ss<<i; ss>>name_num; file_name = name_num + ".txt"; infile.open(file_name); if(infile.fail()){ cout<<"Open file failed!"<<endl; return false; } unordered_map<string,int>::const_iterator got; unordered_map<string,int> word_num; int k = 0; while(getline(infile,tmp)){ k = 0; got = word_num.find(tmp); if(got == word_num.end()){ word_num.insert(make_pair<string,int>(tmp,1)); } else ++word_num[tmp]; } infile.close(); outfile[i].open(file_name); if(outfile[i].fail()){ cout<<"Open file failed"<<endl; return false; } //檔案排序 vector<pair<string,int>> pair_vec; for(unordered_map<string,int>::iterator it = word_num.begin(); it != word_num.end(); ++it){ pair_vec.push_back(make_pair<string,int> (it->first,it->second)); } sort(pair_vec.begin(),pair_vec.end(),mysort); for(vector<pair<string,int>>::iterator it = pair_vec.begin(); it != pair_vec.end(); ++it){ outfile[i]<<it->first<<" "<<it->second<<endl; } outfile[i].close(); } return true; } int main() { //產生資料 if(!Generate_Data()) return EXIT_FAILURE; //資料分組為50個組,並好排序 ifstream infile; stringstream ss; string name_num, file_name,tmp,tmp1; int num; ofstream outfile("result.txt"); string str("data.txt"); if(!Split_Into_Groups(str)) return EXIT_FAILURE; //獲取每個檔案的第一個,然後排序,儲存結果 vector<pair<string,int>> res; for(int i = 0; i < 50; ++i){ ss.clear(); ss<<i; ss>>name_num; file_name = name_num + ".txt"; infile.open(file_name); if(infile.fail()){ cout<<"Open file failed!"<<endl; return false; } if(getline(infile,tmp)){ size_t found = tmp.find_last_of(" "); if(found != string::npos){ tmp1 = tmp.substr(0,found); num = atoi((tmp.substr(found+1)).c_str()); } res.push_back(make_pair<string,int>(tmp1,num)); } infile.close(); } sort(res.begin(),res.end(),mysort); for(vector<pair<string,int>>::iterator it = res.begin(); it != res.end(); ++it){ outfile<<it->first<<" "<<it->second<<endl; } outfile.close(); cin.get(); return 0; }