我从 CLRS 完成的这个合并排序代码有什么问题?

问题描述

输出错误! 我已经尝试了每一个条件,但未能得到真正的结果

我试图从 clrs 书中的伪代码中实现这一点,但我失败了。 我正在尝试使用迭代器编写合并排序,以在 c 语言中实现自己的伪代码,但由于某种原因,此代码正在编译但结果未排序。有人能弄清楚它有什么问题吗?对我未经训练的眼睛来说,这似乎完全没问题。

#include <stdio.h>
#include<math.h>
#include <stdlib.h>

int a[] = {5,3,65,6,7,8};

void print_array(int a[],int size)
{
    int i;
    for(i = 0;i < size;i++)
    {
        printf("%d ",a[i]);
    }
}
void merge(int a[],int p,int q,int r)
{
    int n1,n2,i,j,k;
    n1 = q - p + 1;
    n2 = r - q;
    int l[n1];
    int m[n2];
    for(i = 0; i < n1; i++)
        l[i] = a[i+p];
    for(j = 0; j < n2; j++)
        m[j] = a[q+1+j];
    l[n1] = 9999999;
    m[n2] = 9999999;
    i = 0;
    j = 0;
    for(k = p;k < r; k++)
    {
        if(l[i] <= m[j])
        {
            a[k] = l[i];
            i = i+1;
        }
        else
        {
            a[k] = m[j];
            j = j+1;
        }
    }
}
void merge_sort(int a[],int r)
{
    if(p < r)
    {
        int q = floor((p + r) / 2);
        merge_sort(a,p,q);
        merge_sort(a,q+1,r);
        merge(a,q,r);
    }
}
int main()
{
    int size = (sizeof(a) / sizeof(a[0]));
    print_array(a,size);
    printf("\n");
    merge_sort(a,size);
    print_array(a,size);
    return 0;
}

//for this input out put is showing
//-1 -1 3 3 3 -1 6 7

解决方法

请注意数组的边界和大小:

  • 你的参数 r 不是数组的大小,而是最右边元素的索引,所以你应该调用 merge_sort(a,size - 1);

  • 当你想使用一个大的哨兵值时,在实际数组之后,你必须为它分配空间,所以:

    int l[n1];
    int m[n2];
    
  • 因为你的值r是最后一个元素的索引,所以在合并的时候一定要考虑,你的循环条件应该是for(k = p; k <= r; k++)

  • (其实不是问题,但您不需要像在 JavaScript 中那样使用 floor。当 ab 是整数时,a / b 会执行结果为整数的除法。)

在 C 中,数组(以及一般的范围)具有包含下限和不包含上限:lo 是第一个有效索引,hi 是有效范围之后的第一个无效索引。对于数组索引,lohi 为零和数组大小。

接受这个约定。 C 索引导致以下样式:

  • 范围的长度为 hi - lo;
  • 前向循环是 for (i = lo; i < hi; i++);
  • 相邻范围共享 hilo 值。

例如,在您的 merge 函数中,中间值 p 将是右侧范围的第一个值,也是左侧范围的唯一上限。

如果伪代码或其他语言的代码使用从一开始的索引,我建议将其翻译成 C 的从零开始的排他上界风格。一段时间后,您会怀疑虚假的 - 1<=:)