繁体   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