簡體   English   中英

使用C ++中的MergeSort排序文件

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM