【问题标题】:Merge Sort issue when removing the array copy step删除数组复制步骤时的合并排序问题
【发布时间】:2013-10-20 21:32:03
【问题描述】:

我已经有一段时间无法调试了。我正在尝试通过遵循“C++ 中的算法”一书中的 Robert Sedgewick 的算法来实现没有额外的数组复制步骤的 MergeSort 算法。
算法的简短描述:

递归程序设置为对 b 进行排序,将结果留在 a。因此,编写递归调用以将其结果留在 b 中,我们使用基本的合并程序将这些文件从 b 合并到 a 中。这样,所有的数据移动都是在合并过程中完成的。

问题是我找不到任何逻辑错误,但排序不正确。数据在某处被覆盖,我无法确定是什么逻辑错误导致了这种情况。程序结束时数据已排序,但不再是相同的数据。
例如,输入数组:{ A, Z, W, B, G, C } 生成数组:{ A, G, W, W, Z, Z }

我显然可以看出这一定是某个地方的逻辑错误,但我已经尝试调试了很长时间,我认为一双新的眼睛可能会看到我缺少的东西,因为我真的可以'没有发现任何问题。

我正在运行的完整代码:

//Here is my complete code that I run and that behaves as specified above.

#include <iostream>
#include <stdlib.h>

using namespace std;

// function to print the array
void print(char * a[],int l, int r)
{ for(int i=l;i<=r;i++) cout << (i+1) << ": " << a[i] << endl; }

static const int M = 1;

void insertion(char** a, int l, int r)
{ int i,j;
  char * temp;
  for(i=1;i<r+1;i++)
  { temp = a[i];
    j = i;
    while((j>0) && strcmp(a[j-1],temp)>0)
    { a[j] = a[j-1];
      j = j - 1; }
     a[j] = temp; } }

//merging a and b into c
void merge(char ** c,char ** a, int N, char ** b, int M)
{ for (int i=0, j=0, k=0; k<(N+M); k++)
  { if(i == N) {c[k] = b[j++]; continue; }
if(j == M) {c[k] = a[i++]; continue; }
c[k] = strcmp(a[i], b[j])<0 ? a[i++] : b[j++]; } }

 void mergesortAux(char ** a, char ** b, int l, int r)
 { if(r-l <= M) { insertion(a, l, r); return; }
   int m = (l+r)/2;
   mergesortAux(b, a, l, m);        //merge sort left
   mergesortAux(b, a, m+1, r);      //merge sort right
   merge(a+l,b+l,m-l+1,b+m+1,r-m);  }       //merge

void mergesort(char ** a,int l, int r, int size)
{ static char ** aux = (char**)malloc(size*sizeof(char*));
  for(int i = l; i<size; i++) aux[i] = a[i];
  mergesortAux(a,aux,l,r); }
 //free(aux); } I removed this piece of code as suggested, I realize it's unnecessary 

int main(int argc, char * argv[]) 
{ int size = 6;
  char **data = (char**)malloc(size*sizeof(char*));
  data[0] = "A";
  data[1] = "Z";
  data[2] = "W";
  data[3] = "B";
  data[4] = "G";
  data[5] = "C";

  print(data,0,size-1);
  printf("---------------------------\n");

  mergesort(data,0,size-1,size);

  printf("---------------------------\n");
  print(data,0,size-1);
  return 0;
}

输出:

1: A
2: Z
3: W
4: B
5: G
6: C
---------------------------
---------------------------
1: A
2: G
3: W
4: W
5: Z
6: Z

【问题讨论】:

标签: c algorithm sorting mergesort


【解决方案1】:

你的整个代码完全搞砸了。

您将输入数组与输出数组混淆了,并试图始终就地排序。你的代码格式很糟糕。你的变量名很糟糕。您正在使用冗余参数(您正在传递size 以及索引范围lr)。您混淆了索引范围的含义。这段代码有很多问题,我可以在这里描述一整晚。

但是,这里只有最后一个是关键的:

在这一行:

{ if(r-l <= M) { insertion(a, l, r); return; }

您尝试将数组al 排序到r 部分。但是,l 索引 未在 insertion 函数中使用,因此它将 a0 修改为 r(含)。 r 表明它是正确的索引,但在此方法中用作数组的大小。

最简单的解决方法是将其更改为:

if(r-l <= M) { insertion(a+l, l, r-l); return; }

但修复insertion 方法以正确处理索引可能是一个更好的主意。

另外,我强烈建议您清理整个代码。这是不可维护的。这是不可读的。这是C 最黑暗的一面。我永远无法理解为什么人们不能使用易于理解的函数/变量名称,使用结构来表示复合概念并将逻辑划分为小的 可读 部分。好像写 C 迫使你认为你正在设置处理器寄存器中的各个位,并且不能使用长度超过 1 个字符的变量名。

即使是你——这段代码的作者也有理解它的问题。这是一个强烈的建议,它存在一些严重的问题:)

抱歉让我失望了,我无法抗拒这个谜题,在这上面浪费了很多时间:)

【讨论】:

  • 我知道格式不好,但我可以看到它实际上更糟:) 感谢您的帮助和批评,现在一切正常,我将开始清理代码现在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-15
  • 1970-01-01
  • 2013-05-02
  • 2012-08-17
  • 1970-01-01
  • 2020-05-26
  • 2021-06-22
相关资源
最近更新 更多