删除阵列复制步骤时合并排序问题

时间:2013-10-20 21:32:03

标签: c algorithm sorting mergesort

我遇到了一个我无法调试很长时间的问题。我正在尝试实现一个MergeSort算法,没有额外的数组复制步骤,遵循Robert Sedgewick的算法,并且在C ++"算法中使用#C;"本书。
算法的简短描述:

  

递归程序设置为排序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

1 个答案:

答案 0 :(得分:2)

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

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

然而,这里只有最后一个是至关重要的:

在这一行:

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

您尝试对数组l的{​​{1}}到r部分进行排序。但是,a函数中的l索引未使用,因此它会将insertiona修改为0r表明它是正确的索引,但在此方法中用作数组的大小。

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

r

但是修复if(r-l <= M) { insertion(a+l, l, r-l); return; } 方法来正确处理索引可能是个更好的主意。

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

即使您 - 此代码的作者也难以理解它。这是一个强烈的建议,它有一些严重的问题:)

对于沮丧感到抱歉,我无法抗拒这个谜题,浪费了很多时间在这上面:)