【问题标题】:Insertion and Merge Sorts Does not Work on Big Data Sets C++插入和合并排序不适用于大数据集 C++
【发布时间】:2016-10-08 19:25:17
【问题描述】:

我一直在尝试为从文件中读取的数据集编写插入和合并排序。在测试我的代码时,我使用了一个小数据集(包括 6 个数字)并且我的程序运行良好。但是当我使用具有 1000000 个输入的更大数据集时,代码不起作用,我不明白为什么。我试图将向量的类型更改为双精度,但它并没有解决问题。 提前感谢您的所有帮助。

我的数据集由以下数字组成:512069、12823、11628

这是我的代码:

  vector<int> readFile(string fileName);
    void display(vector<int> &vector);
    void insertionSort(vector<int> &vec);
    vector<int> merge(vector<int> left, vector<int> right);
    vector<int> mergeSort(vector<int> &m);

int main(int argc, const char * argv[]) {

    string fileName;
    cout<<"Enter input file name :";
    cin>>fileName;

    vector<int> numbersVec = readFile(fileName);
    display(numbersVec);

    cout<<"INSERTION SORT"<<"\n";
    insertionSort(numbersVec);
    display(numbersVec);

    cout<<"MERGE SORT"<<"\n";
    vector<int> neu = mergeSort(numbersVec);
    display(neu);


    return 0;
}


vector<int> readFile(string fileName){

    vector<int> numbers;
    ifstream in(fileName,std::ios::in);

    if(!in.is_open())
    {
        cout << "File Cannot be Opened" << endl;
    }

    else{

        int number;
        while (in >> number) {
            numbers.push_back(number);
        }
    }

    in.close();
    return numbers;
}


void display(vector<int> &vec) {

    for(int i = 0; i < vec.size(); i++)
    {
        cout << vec[i] << " ";
    }
    cout << "\n" << endl;

}


void insertionSort(vector<int> &vec) {

    long double i, j, tmp;

    for (i = 1; i < vec.size(); i++) {

        j = i;

        while (j > 0 && vec[j - 1] > vec[j]) {

            tmp = vec[j];
            vec[j] = vec[j - 1];
            vec[j - 1] = tmp;
            j--;

        }
    }
}


vector<int> merge(vector<int> tmpl, vector<int> tmpr){

    vector<int> res;

    while ((int)tmpl.size() > 0 || (int)tmpr.size() > 0) {

        if ((int)tmpl.size() > 0 && (int)tmpr.size() > 0) {

            if ((int)tmpl.front() <= (int)tmpr.front()) {

                res.push_back((int)tmpl.front());
                tmpl.erase(tmpl.begin());

            }

            else {

                res.push_back((int)tmpr.front());
                tmpr.erase(tmpr.begin());

            }

        }
        else if ((int)tmpl.size() > 0) {

            for (int i = 0; i < (int)tmpl.size(); i++)

                res.push_back(tmpl[i]);

            break;
        }

        else if ((int)tmpr.size() > 0) {

            for (int i = 0; i < (int)tmpr.size(); i++)

                res.push_back(tmpr[i]);

            break;

        }

    }

    return res;

}


vector<int> mergeSort(vector<int> &vec)
{
    if (vec.size() <= 1)

        return vec;

    vector<int> tmpl, tmpr, res;

    int mid = ((int)vec.size()+ 1) / 2;

    for (int i = 0; i < mid; i++) {

        tmpl.push_back(vec[i]);

    }

    for (int i = mid; i < (int)vec.size(); i++) {

        tmpr.push_back(vec[i]);

    }

    tmpl = mergeSort(tmpl);

    tmpr = mergeSort(tmpr);

    res = merge(tmpl, tmpr);

    return res;
}

【问题讨论】:

  • 大数据集有哪些错误?永远循环还是别的什么?在insertionSortijtmp 中应该有int 类型,但不是long double。您的 mergeSort 函数似乎效率低下(多向量副本:合并可能到位)。
  • 它在打印出 INSERTION SORT 后进入无限循环,我尝试使用调试器几乎不可能跟踪如此大的集合。我还将 i, j, tmp 更改为 int,但它仍然没有跳出循环。
  • 这是一个复杂性问题。您的插入排序是 n(n-1)/2 其中 n 是向量的大小。即使你的vector只有100万条数据,你也会等很久。
  • 这些都不是问题,但不要使用std::endl,除非你需要它做的额外东西; '\n' 结束一行。而且你不需要在readFile的末尾关闭输入流;流的析构函数会这样做。
  • 谢谢 Franck,但是有没有办法解决呢?我认为使用向量会更节省内存,使用数组来保存我的数据会加速吗?由于我的教授给了我数据集,我知道我最多会有 100 万个数据。

标签: c++ sorting dataset mergesort insertion-sort


【解决方案1】:

您的算法看起来不错。这只是复杂性的问题。如果计算插入排序算法的while 执行的次数,平均而言,它接近n(n-1)/2,其中n 是您的数据集的大小(请参阅insertion sort)。

如果 n=1.000.000,复杂度接近 500.000.000.000,非常长。

只需尝试在main 中评论对insertionSort 的调用,您的main 函数应该会提前结束。

请注意,即使您在您的mergeSort 算法中(也)做了多个vector 副本,它也会提前终止。复杂度为 'n * log(n)'(参见 merge sort)。

【讨论】:

  • 我在发布这个问题之前也尝试过这样做,但我没有看到答案,但如果告诉你我等了太久才看到结果,那将是一个谎言。这是算法分析课的作业,所以我需要添加clock() 并针对不同的数据大小(例如1000、10000、100000、1000000 输入)运行代码。所以我从你的回答中了解到,如果我等待的时间足够长,我应该会得到结果,对吧?
  • 是的,如果您等待的时间足够长,您应该会得到结果。如何在不同的数据大小之间改变你的时间? 10000 的时间应该比 1000 慢 100 倍。100000 的时间应该比 1000 慢 10000 倍。因此,您应该从 1000 的时间推断任何数据集的时间。
  • 我尝试了一组 1000 个数字并得到了结果。非常感谢您的时间和帮助!
猜你喜欢
  • 1970-01-01
  • 2019-09-12
  • 1970-01-01
  • 2021-08-25
  • 1970-01-01
  • 2021-07-01
  • 2016-01-31
  • 2011-09-12
  • 1970-01-01
相关资源
最近更新 更多