C 朴素指针算术合并排序返回错误

C 朴素指针算术合并排序返回错误,c,pointers,mergesort,C,Pointers,Mergesort,试图使用指针算法实现一个简单的合并排序,但它返回的是无意义的结果。我遵循的惯例是,l是最左边的有效索引,r是最右边的有效索引 输入是51324,但它返回:01025,预期输出自然是12345 #include <stdio.h> void mergeptr(int *array, int l, int m, int r) { int tmp[r - l + 1]; int *tptr = &(tmp[0]); int *lptr = &(ar

试图使用指针算法实现一个简单的合并排序,但它返回的是无意义的结果。我遵循的惯例是,
l
是最左边的有效索引,
r
是最右边的有效索引

输入是
51324
,但它返回:
01025
,预期输出自然是
12345

#include <stdio.h>

void mergeptr(int *array, int l, int m, int r)
{
    int tmp[r - l + 1];
    int *tptr = &(tmp[0]);
    int *lptr = &(array[l]);
    int *rptr = &(array[m]);

    /* Find the smallest in each side */
    while ((lptr < &array[m]) && (rptr < &array[r]))
        if (*lptr <= *rptr) *tptr++ = *lptr++;
        else                *tptr++ = *rptr++;

    /* Copy the remaining */
    while (lptr < &array[m]) *tptr++ = *lptr++;
    while (rptr < &array[r]) *tptr++ = *rptr++;

    /* Copy back */
    for (size_t i = 0; i < (r-l+1); ++i)
        array[l+i] = tmp[i];
}

void merge_sort(int *array, int l, int r) {
    if (l < r) {
        int m = (l + r) / 2;
        merge_sort(array, l, m);
        merge_sort(array, m + 1, r);
        mergeptr(array, l, m, r);
   }
}

int main(void) { 
    int values[5] = { 5, 1, 3, 2, 4 };

    merge_sort(&values[0], 0, 4);
    for (size_t i = 0; i < 5; ++i)
        printf("%d ", values[i]);
    printf("\n");

    return 0;
}
#包括
void mergeptr(int*数组、int l、int m、int r)
{
int tmp[r-l+1];
int*tptr=&(tmp[0]);
int*lptr=&(数组[l]);
int*rptr=&(数组[m]);
/*找出两边最小的*/
而((lptr<&array[m])和&(rptr<&array[r]))

如果(*lptr您在处理边界时应该小心。
您的
merge\u sort
函数似乎正在处理范围
[l,r)
(包括
l
,不包括
r
),因此:

  • 不应执行元素
    m
    merge\u sort(数组,m+1,r);
    merge\u sort(数组,m,r);
  • 当只有1个元素时,不需要排序:
    if(l
    应该是
    if(l+1
  • mergeptr
    函数中的
    r-l+1
    r-l+1
    应为
    r-l
    r-l
固定代码:

#include <stdio.h>

void mergeptr(int *array, int l, int m, int r)
{
    int tmp[r - l];
    int *tptr = tmp;
    int *lptr = array + l;
    int *rptr = array + m;

    /* Find the smallest in each side */
    while( (lptr < (array + m)) && (rptr < (array + r)))
        if( *lptr <= *rptr) *tptr++ = *lptr++;
        else                *tptr++ = *rptr++;

    /* Copy the remaining */
    while(lptr < (array + m)) *tptr++ = *lptr++;
    while(rptr < (array + r)) *tptr++ = *rptr++;

    /* Copy back */
    for(size_t i = 0; i < (r-l); ++i)
        array[l+i] = tmp[i];
}

void merge_sort(int *array, int l, int r) {
    if (l + 1 < r) {
        int m = (l+r)/2;
        merge_sort(array, l, m);
        merge_sort(array, m, r);
        mergeptr(array, l, m, r);
   }
}

int main(void) { 
    int values[5] = { 5, 1, 3, 2, 4 };

    merge_sort(values, 0, 5);
    for(size_t i = 0; i < 5; ++i)
        printf("%d ", values[i]);
    printf("\n");

    return 0;
}
#包括
void mergeptr(int*数组、int l、int m、int r)
{
int-tmp[r-l];
int*tptr=tmp;
int*lptr=array+l;
int*rptr=array+m;
/*找出两边最小的*/
而((lptr<(数组+m))&&(rptr<(数组+r)))

if(*lptr)您是否尝试调试它?在函数中添加一些额外的printf以显示调试跟踪。这是使用lerning C“[32,52]”值(第34行)
&array[r]的方法
未定义的行为对吗?我想你需要做一些更改吗?@SaiSreenivas根据5.7加法运算符,指针指向最后一个元素后一个应该是有效的。遗憾的是,许多教程和老师提倡将两个边界都包括在内的约定。这会导致代码繁琐且容易出错。Making
r
excluded允许使用更简单的代码,如图所示。