【问题标题】:C : Mergesort - what is the mistake? Wrong output (repetition)C : Mergesort - 什么是错误?错误输出(重复)
【发布时间】:2011-03-20 14:33:53
【问题描述】:

我已经用 C 语言编写了这个“合并排序”。我认为在将元素复制回原始数组时存在错误。 有人能帮我吗?

提前非常感谢。

enter code here

 /*************************** Merge sort ********************************/
  #include <stdio.h>

  void merge(int arr[], int start1, int end1, int start2, int end2)
  {
   int temp[100], beg1, beg2, i;

   beg1=start1;
   beg2=start2;
   i=0;

   while((beg1<=end1)&&(beg2<=end2))
   {
     if(arr[beg1]<arr[beg2])
      {
        temp[i++]=arr[beg1++];
      }
     else
      {
        temp[i++]=arr[beg2++];
      }
   }
   if(beg1<end1) {
       while(beg1<=end1) temp[i++]=arr[beg1++];
   }

  if(beg2<end2) {  
       while(beg2<=end2) temp[i++]=arr[beg2++];
  }

  i=0;
  for(beg1=start1; beg1<=end1; beg1++)
  {
      arr[beg1]=temp[i++];
  }
 for(beg1=start2; beg1<=end2; beg1++)
  {
      arr[beg1]=temp[i++];
  }
}

 void mergesort(int arr[], int beg, int end)
 {
   int mid;

   if(beg<end) {
      mid=(beg + end)/2;
      mergesort(arr, beg, mid);
      mergesort(arr, mid+1, end);
      merge(arr, beg, mid, mid+1, end);
   }
 }

 int main()
 {
   int i;
   int arr[]={34, 3, 10, 78, 4, 0, 14};
   mergesort(arr, 0, 6);

   printf("Here are the sorted elements:\n");

   for(i=0; i<6; i++){
      printf("%d\t",arr[i]);
   }
   printf("\n");
 }

Output:
  [root@dhcppc0 sorting]# gcc mergesort.c
  [root@dhcppc0 sorting]# ./a.out

     Here are the sorted elements:
          0       0       3       0       10      10

【问题讨论】:

  • 调试这类问题的一个好方法是在中间步骤中打印出数组的元素(就像你在最后做的那样)。这通常可以清楚地说明哪里出了问题。
  • 我接受,但如果你有任何现成的算法,你能帮忙吗?我的面试时间太短了,还有很多其他的准备工作。此外,这是一个递归程序,打印元素可能非常麻烦。 GDB 可以提供帮助,但又是时间因素。
  • @kingsmasher1:你是说这是为了当前的采访?
  • 你的面试时间?面试不是你应该自己做的吗?
  • 在递归函数中打印元素可能很麻烦,但由于您可以仅使用 7 元素数组来重现问题,因此不会太糟糕。使用 print 调试递归函数时,一种方便的技术是使用全局变量确定缩进级别。让您的 print_elements 函数从打印那么多空格开始,并在您输入 mergesort() 时增加变量并在您离开时减少它。

标签: c mergesort


【解决方案1】:

end1end2 是有效的索引,所以我认为你不应该在这里有那些 if 语句

if(beg1<end1) {
   while(beg1<=end1) temp[i++]=arr[beg1++];
}

if(beg2<end2) {  
   while(beg2<=end2) temp[i++]=arr[beg2++];
}

如果beg1 == end1 会怎样?

如果beg1&lt;end1,则在 [beg1, end1] 范围内至少还有 2 个数组元素。如果只有一个,你也应该复制它。您应该让循环不受 if 语句的保护。将上面显示的代码更改为:

//if(beg1<end1) {
   while(beg1<=end1) temp[i++]=arr[beg1++];
//}

//if(beg2<end2) {  
   while(beg2<=end2) temp[i++]=arr[beg2++];
//}

附带说明,您的排序不稳定。要修复它,请更改此条件

if(arr[beg1]<arr[beg2])

if(!(arr[beg2]<arr[beg1]))

【讨论】:

  • @Maciej:谢谢你的回答,但我不认为你说的是​​真的。在这里,我们与实际数组值(arr[beg1] 或 arr[beg2])无关,我们正在做的是检查两个指针​​(不是字面上的指针)的索引是否没有完全到达数组末尾。如果剩下任何一个,我们只是复制它。
  • @Maciej 如果条件肯定需要这些,请考虑一下。
  • @Algorithmist 好吧,也许我们有误会。我不建议删除所有内容。我是说,循环可以无条件执行。
  • @kingsmasher1 排序不稳定的事实是另一个小问题,不是您要问的问题,但是合并排序可以稳定并且一个好的实现是,所以我在最后添加了评论。
  • @Maciej:但你的 cmets 在这种情况下不成立。更改为您所说的内容也不会使其稳定。但是会出错。
猜你喜欢
  • 1970-01-01
  • 2022-10-13
  • 1970-01-01
  • 2022-12-13
  • 2020-11-25
  • 1970-01-01
  • 1970-01-01
  • 2014-09-15
  • 2015-09-13
相关资源
最近更新 更多