【问题标题】:Garbage value in merge sort归并排序中的垃圾值
【发布时间】:2014-07-21 16:10:15
【问题描述】:

在编写一个简单的归并排序算法时,我遇到了一个奇怪的问题。

代码运行良好,直到我在 mergeSort 函数的 return 语句之前添加任何 printf() 语句。 如果我删除那个 printf() 语句,那么垃圾值就会出现在输出中。

仅当要排序的数组的第一个元素是最大元素时才会发生这种情况。

#include<stdio.h>
#include<malloc.h>
int* mergeSort(int*,int,int);

int main()
{
    int arr[] = {10,2,5,6,7,0,3,1,8};
    int i;
    int* a = mergeSort(arr,0,8);

    for(i=0;i<9;i++)
        printf("%d ",a[i]);

    printf("\n bye");
    return 0;
}

int* mergeSort(int *arr, int left, int right)
{
    int mid = (left+right)/2;
    int len = right-left+1;
    int* result = (int*) malloc(sizeof(int)*(len)), *arr1,*arr2;
    int i=0;
    int l1,l2,r1,r2;
    l2 = mid+1;

    i = 0;
    if(len < 3)
    {
        if(len == 2)
        {
            if(arr[left] > arr[right])
            {
                result[0] = arr[right];
                result[1] = arr[left] ;
            }
            else
            {
                result[0] = arr[left];
                result[1] = arr[right];
            }

            return result;
        }
        else
        {
            result[0] = arr[left];
            return result;
        }
    }

    arr1 = mergeSort(arr,left,mid);
    arr2 = mergeSort(arr,l2,right);
    l1 = 0;
    l2 = 0;
    r1 = mid-left;
    r2 = right-l2;

    while(i<len)
    {
        if(l1 > r1)
        {
            // put rest of arr2 in result and return
            while(i<len)
            {
                result[i] = arr2[l2];
                i++;
                l2++;

            }
                free(arr1);
                free(arr2);
                return result;
        }
        else if(l2 > r2)
        {
            // put rest of arr1 in result and return
            while(i<len)
            {
                result[i] = arr1[l1];
                i++;
                l1++;

            }

                free(arr1);
                free(arr2);
                return result;
        }

        if(arr1[l1] > arr2[l2])
        {
            result[i] = arr2[l2];
            l2++;
            i++;
        }
        else
        {
            result[i] = arr1[l1];
            l1++;
            i++;
        }       
    }

    free(arr1);
    free(arr2);

    //printf("Stackoverflow"); // I have to add this to make it work
    return result;
}

如果我评论倒数第三个,那么代码将返回垃圾值。

为什么会出现这个问题?我该如何解决?

这里是我在没有/使用 printf("Stackoverflow") 语句的情况下得到的输出屏幕截图的链接:http://i.stack.imgur.com/OPqyd.jpg

注意:它似乎在其他开发人员的系统中工作,我在 mingw32 中使用 gcc 3.4.2。

答案:正如 Matt McNabb 和 Mahonri Moriancumer 指出的那样,这似乎是由于我的代码中的逻辑错误而发生的。

【问题讨论】:

  • &lt;malloc.h&gt;?最好用&lt;stdlib.h&gt;,这是标准的。
  • 不带 / 带 printf("Stackoverflow");我得到相同的输出!还有其他具体细节吗?
  • 在// put rest of arr2 in result and return 和// put rest of arr1 in result and return 块中,每个while() 循环的底部都有一个return 语句;这使得这些“非循环”。这是故意的吗?
  • @MahonriMoriancumer 是的。
  • @Sathish 现在什么都没有,但我正在尝试获取更多信息。它是否显示正确的输出?

标签: c sorting mergesort


【解决方案1】:
l1 = 0; 
l2 = 0; 
r1 = mid-left; 
r2 = right-l2;

应该是:

r1 = mid-left; 
r2 = right-l2;
l1 = 0; 
l2 = 0; 

Not working
Working

在实现之间看到的不同行为将取决于在您跑完 arr2 之后的垃圾。

我强烈建议您使用可读的变量名称(不是l1!)并注释您的代码以表明它在做什么,并且不要重复使用变量。在需要时声明变量。如果代码是这样,您会更快发现问题:

int arr2_starts_at = mid + 1;
// ....

int arr1_iter = 0;
int arr2_iter = 0;

// One less than the number of items in each part
int arr1_iter_limit = mid - left;
int arr2_iter_limit = right - arr2_iter;   // should be arr2_starts_at

实际上,您应该将l1 和l2 的定义放在arr1_length 等的计算之后,所以您永远不会遇到问题。

我也更喜欢使用您正在迭代的长度,而不是您停止的索引,例如

// no comment required, "arr1_length" says it all
int arr1_length = mid - left + 1;

【讨论】:

  • 谢谢@Matt McNabb,这已经解决了垃圾值的问题,但是您知道为什么它在我的代码中使用 printf 而不是没有它吗?
  • 当未定义的行为发生时,任何事情都可能发生。可能数组末尾的幻像条目都恰好包含在这种情况下不影响排序顺序的值。
猜你喜欢
  • 2020-05-14
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 1970-01-01
  • 1970-01-01
  • 2022-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多