按值传递的C ++合并排序

时间:2017-10-12 05:08:29

标签: c++ sorting recursion mergesort

我试图通过仅向函数传递向量值(没有左或右索引)来递归地实现合并排序算法。当要排序的列表作为指针void merge_sort_array(int* v, int l, int r)或引用void merge_sort_ref(vector<int>& v, int l, int r)传递时,以下代码中的while循环有效,但我不能理解为什么以下代码无法正确排序我的列表。我觉得这与i, j, k的起始值或我的while循环中的界限有关,但我已经尝试了任何对我有意义且无法弄清楚的东西。

#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <algorithm>

using namespace std;
vector<int> merge_sort_value(vector<int> v) {
    int n = v.size();
    if(n == 1){
        return v;
    }
    else{
        int m = n/2;
        vector<int> v1(v.begin(), v.begin()+m);
        vector<int> v2(v.begin()+m, v.begin()+n);
        merge_sort_value(v1);
        merge_sort_value(v2);
        vector<int> tmp(v.begin(), v.begin()+m);
        int i = 0;
        int j = m;
        int k = 0;
        while((i < m) or (j < n)){
            if(i == m){
                v[k] = v[j];
                j +=1;
            }
            else if((j == n) or (tmp[i] < v[j])){
                v[k] = tmp[i];
                i+=1;
            }
            else{
                v[k] = v[j];
                j+=1;
            }
            k+=1;
            # print output for debugging
            for(auto x = v.begin(); x != v.end(); ++x)
                cout << *x << " ";
            cout << "" << endl;
            cout <<  i << "\t"<< j << "\t" << k << endl;
        }
        return v;
    }
}

int main(int argc, char** argv) {
    vector<int> v(10);

    for(int i=0; i < 10; ++i)
      v[i] = rand() % 100;

    v = merge_sort_value(v);
    return 0;
}

我已经提供了一个示例输出供以下参考:

28 28 
0   2   1
28 80 
1   2   2
21 21 
0   2   1
21 92 
1   2   2
14 92 21 
1   1   1
14 92 21 
1   2   2
14 92 21 
1   3   3
14 28 14 92 21 
0   3   1
14 80 14 92 21 
1   3   2
14 80 28 92 21 
2   3   3
14 80 28 92 21 
2   4   4
14 80 28 92 21 
2   5   5
21 57 
1   1   1
21 57 
1   2   2
78 83 
1   1   1
78 83 
1   2   2
78 78 83 
0   2   1
78 83 83 
0   3   2
78 83 96 
1   3   3
21 57 96 78 83 
1   2   1
21 57 96 78 83 
2   2   2
21 57 96 78 83 
2   3   3
21 57 96 78 83 
2   4   4
21 57 96 78 83 
2   5   5
21 28 14 92 21 21 57 96 78 83 
0   6   1
21 57 14 92 21 21 57 96 78 83 
0   7   2
21 57 80 92 21 21 57 96 78 83 
1   7   3
21 57 80 28 21 21 57 96 78 83 
2   7   4
21 57 80 28 14 21 57 96 78 83 
3   7   5
21 57 80 28 14 92 57 96 78 83 
4   7   6
21 57 80 28 14 92 21 96 78 83 
5   7   7
21 57 80 28 14 92 21 96 78 83 
5   8   8
21 57 80 28 14 92 21 96 78 83 
5   9   9
21 57 80 28 14 92 21 96 78 83 
5   10  10

谢谢,非常感谢任何帮助!

1 个答案:

答案 0 :(得分:0)

在审核了您的代码后,您似乎在自己的算法中犯了错误,在C ++中作为语言犯了错误,所以我编辑了您的算法更整洁,更易读的算法我会解释一些部分的代码

代码

#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <algorithm>

using namespace std;
vector<int> merge_sort_value(vector<int> v) {
  int n = v.size();
  if(n == 1){
    return v;
  }
  else{
    int m = n/2;
    vector<int> v1(v.begin(), v.begin()+m);
    vector<int> v2(v.begin()+m, v.begin()+n);
    v1 = merge_sort_value(v1); /* passing by value will left v1 with no sorting so you need to copy from the returned
    object */
    v2 = merge_sort_value(v2);
    int i = 0;
    int j = 0;
    int k = 0;
    const size_t left_vecS = v1.size();
    const size_t right_vecS = v2.size();

    while (i<left_vecS&&j<right_vecS) { // we must keep i (AND) j  valid
      if (v1[i] < v2[j])
        v[k++] = v1[i++];

      else
        v[k++] = v2[j++];
    }

      while(i<left_vecS) // if we sorted v2 then what insert the rest of v1 in v as what kept from v1 will be sorted
        v[k++] = v1[i++];


      while(j<right_vecS)
        v[k++] = v2[j++];
    }
    return v;
  }


int main(int argc, char** argv) {
  vector<int> v(10);
  std::vector<int> x;

  for(int i=0; i < 10; ++i)
    v[i] = rand() % 100;

  v = merge_sort_value(v);

  for(auto&i:v)
    std::cout << i << std::endl;

  return 0;
}

1 - 我摆脱了排序功能中的打印,因此我们保持代码清洁

<强> 2 -  您在语言级别所做的第一个错误是您没有将返回的排序矢量对象从merge_sort_value复制到矢量。(我在评论的代码中提到了这一点) )这是首先要记住的事情

3 - 算法的逻辑部分对我来说并不清楚,因为我没有看到你如何特别排序那部分else if ((j == n) or (tmp[i] < v[j])) { v[k] = tmp[i]; i += 1; } < / p>

像你一样,将未分类的子矢量与另一个未分类的矢量进行比较,然后再次给它未分类的值(你必须将v1与v2进行比较) 整个逻辑错过了我认为你需要审查它

无论如何,我希望有所帮助