[英]Order files with MergeSort in c++
我正在嘗試實現自己的MergeSort,但遇到了一些問題,看看是否有人可以幫助我。
我有一個很大的文件,其中一些信息用逗號分隔(名稱,城市,郵件,電話)。 我想應用mergesort對其進行排序,因為我認為客戶端計算機一次嘗試將沒有足夠的內存來進行排序。
因此,我將其拆分為MAX_CUSTOMERS行的文件,並分別對其進行排序,直到此處都正確為止,但是當我想獲取前兩個文件並對其進行排序時,我遇到了所有問題,我遇到了重復的問題和其他問題消失,這是我的代碼:
void MergeSort(string file1Name, string file2Name,string name){
printf("Enter MERGE SORT %s AND %s\n",file1Name.c_str(),file2Name.c_str());
string temp;
string fileName;
string lineFile1, lineFile2;
bool endFil1 = false, endFil2 = false;
int numCust1 = 0;
int numCust2 = 0;
int x1 = 0, x2 = 0;
ifstream file1;
file1.open(file1Name.c_str());
ifstream file2;
file2.open(file2Name.c_str());
ofstream mergeFile;
fileName = "customers_" +name +".txt";
cout << "Result file " << fileName << endl;
mergeFile.open("temp.txt");
getline(file1,lineFile1);
getline(file2,lineFile2);
while(!endFil1 && !endFil2){
if(CompareTelf(lineFile1,lineFile2)==1){
mergeFile << lineFile1 << endl;
if(!getline(file1,lineFile1)){
cout << lineFile1 << endl;
cout << "1st file end" << endl;
endFil1 = true;
}
}else{
mergeFile << lineFile2 << endl;
if(!getline(file2,lineFile2)){
cout << lineFile2 << endl;
cout << "2nd file end" << endl;
endFil2 = true;
}
}
}
if(endFil1){
//mergeFile << lineFile2 << endl;
while(getline(file2,lineFile2)){
mergeFile << lineFile2 << endl;
}
}else{
//mergeFile << lineFile1 << endl;
while(getline(file1,lineFile1)){
mergeFile << lineFile1 << endl;
}
}
file1.close();
file2.close();
mergeFile.close();
rename("temp.txt",fileName.c_str());
return;
}
Customer SplitLine(string line){
string splitLine;
string temp;
Customer cust;
int actProp = 0;
int number;
istringstream readLineStream(line); //convert String readLine to Stream readLine
while(getline(readLineStream,splitLine,',')){
if (actProp == 0)cust.name = splitLine;
else if (actProp == 1)cust.city = splitLine;
else if (actProp == 2)cust.mail = splitLine;
else if (actProp == 3)cust.telf = atoi(splitLine.c_str());
actProp++;
}
//printf("Customer read: %s, %s, %s, %i\n",cust.name.c_str(), cust.city.c_str(), cust.mail.c_str(), cust.telf);
return cust;
}
int CompareTelf(string str1, string str2){
Customer c1 = SplitLine(str1);
Customer c2 = SplitLine(str2);
if(c1.telf<c2.telf)return 1; //return 1 if 1st string its more important than second, otherwise, return -1
else return -1;
}
struct Customer{
string name;
string city;
string mail;
long telf;
};
如果對代碼有疑問,請說出來! 我嘗試使用varNames盡可能描述性!
非常感謝。
您的代碼看起來不錯,但是它有一些缺陷和一個重要的遺漏。
較小的缺陷之一是缺少對Customer
結構的初始化-您沒有為該結構提供構造函數,也沒有對cust
變量進行顯式初始化。 希望字符串成員可以由字符串類構造函數正確初始化,但是long telf
可以獲取任何初始值。
另一個是在分割輸入行時缺少格式檢查。 您確定每個輸入行都具有相同的格式嗎? 如果行中的逗號過多(例如,名稱中的逗號),則循環可能會錯誤地嘗試將“電子郵件”數據分配給“電話”成員...
OTOH如果逗號太少,則'telf'成員可能會保持未初始化狀態,初始值是隨機的...
與第一個缺陷一起,該缺陷可能會導致輸出數據的順序不正確。
使用atoi
函數時也會出現類似的問題:它返回int
但變量為long
。 我想您是因為期望的值范圍而選擇了long
類型-如果是這樣,將輸入數據轉換為int
可能會截斷大部分數據! 我不確定atoi
在這種情況下會做什么,它可能返回轉換輸入字符串的某些初始部分的結果,也可能只是返回零。 這兩個值都是錯誤的,並導致不正確的排序,因此最好改用atol
。
下一個問題是從兩個輸入文件中讀取第一行。 您無需檢查getline()
成功。 如果輸入文件為空,則相應的lineFile_num
字符串將為空,但endFil_num
不會反映該內容-仍為false
。 因此,您再次進入比較無效數據的過程。
最后是主要問題。 假設file1的內容“大於”整個file2的內容(即:大於)。 然后,存儲在lineFile1
的第一行lineFile1
導致CompareTelf()
始終返回-1
。 主循環將整個file2復制到輸出中,然后...? 最后的while()
循環從getline(file1,lineFile1)
開始,從而丟棄了file1的第一行!
由記錄(A,C)和(B)組成的文件將發生類似的結果,這些文件將合並為(A,B,C):首先讀取A和B,然后保存A並讀取C,然后再讀取B保存並檢測到文件2的結尾。 然后while(getline(...))
取消內存中的C並找到文件1的結尾,從而終止了循環。 記錄C丟失。
通常,當主合並循環while(!endFil1 && !endFil2)
耗盡一個文件時,另一個文件的第一未保存行將被丟棄。 為了避免這種情況,您需要存儲第一次讀取的結果:
endFil1 = ! getline(file1,lineFile1);
endFil2 = ! getline(file2,lineFile2);
然后,在主循環之后,開始使用未保存的行復制輸入文件的尾部:
while(!endFil1) {
mergeFile << lineFile1 << endl;
endFil1 = !getline(file1,lineFile1);
}
while(!endFil2) {
mergeFile << lineFile2 << endl;
endFil2 = !getline(file2,lineFile2);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.