【问题标题】:the code of merge_sort doesn`t sort properlymerge_sort 的代码没有正确排序
【发布时间】:2020-09-05 12:10:55
【问题描述】:

我将合并排序编码如下,但它不对数组进行排序。我找不到问题的根源。

void print_arr(int Arr[], int size)

{

    int i;

    for (i = 0;i < size;i++)
        printf(" %d ", Arr[i]);
}

///////////////////////////////////////////

void merge(int Arr[], int left, int mid, int right)

{

    int i = 0, j = 0, k = left;
    int n_l = (mid - left + 1);
    int n_r = (right - mid);
    int* Arr_l = (int*)calloc(n_l , sizeof(int));
    int* Arr_r = (int*)calloc(n_r , sizeof(int));
    if (Arr_l == NULL)
        return;
    if (Arr_r == NULL)
        return;

    for (i = 0;i < n_l;i++)
        Arr_l[i] = Arr[i];

    for (j = 0;j < n_r;j++)
        Arr_r[j] = Arr[mid + 1 + j];

    while (i < n_l && j < n_r)
    {
        if (Arr_l[i] <= Arr_r[j])
        {
            Arr[k] = Arr_l[i];
            i++;
            k++;
        }
        else
        {
            Arr[k] = Arr_r[j];
            j++;
            k++;
        }
    }

    while (i < n_l)
    {
        Arr[k] = Arr_l[i];
        i++;
        k++;
    }

    while (j < n_r)
    {
        Arr[k] = Arr_r[j];
        j++;
        k++;
    }
    free(Arr_l);
    free(Arr_r);
}
////////////////////////////////////////////////////////////////////

void merge_sort_inc(int Arr[], int left, int right)
{

    int mid = (int)((left + (right - 1)) / 2);
    if (left < right)
    {   
        merge_sort_inc(Arr, left, mid);
        merge_sort_inc(Arr, mid + 1, right - 1);
        merge(Arr, left, mid, right);
    }

}

////////////////////////////////////////////////////////////////

int main()

{

    int i;
    time_t t;
    srand((unsigned)time(&t));
    int Array[10];
    int size = sizeof(Array) / sizeof(int);
    for (i = 0;i < size;i++)
        Array[i] = rand() / 100;
    printf(" The unsorted Arrar is : \n\n");
    print_arr(Array, size);

    printf("\n\n The sorted Array is : \n ");

    merge_sort_inc(Array, 0, size);

    print_arr(Array, size);
    return 0;
}

【问题讨论】:

  • int mid = (int)((left + (right - 1)) / 2); 看起来不对,试试int mid = (int)(left + (right - left - 1) / 2);
  • 您似乎使用了独占上限,这很好。如果是这样,则所有+ 1- 1 都不是必需的:跨度[l, r) 的长度是r - l。您的主要问题是合并时的索引:辅助数组分别从 0 到 n_ln_r,但在数组本身中,它们必须在 [left, mid)[mid, right) 范围内。您的代码没有反映这一点。在复制循环中用尽索引后,您必须重新初始化它们。

标签: c sorting


【解决方案1】:
int i = 0, j = 0, k = left;

你应该在while loop之前重置ij的值

    i = 0; j = 0; k = left;  
    while (i < n_l && j < n_r)
    {...}

然后:

for (i = 0;i < n_l;i++)
        Arr_l[i] = Arr[i];

改成

for (i = 0;i < n_l;i++)
        Arr_l[i] = Arr[left+i];

最后,merge_sort_inc 函数应更改为:

void merge_sort_inc(int Arr[], int left, int right) {
    if (left < right)
    {   
        int mid = left + (right - left) / 2;
        merge_sort_inc(Arr, left, mid);
        merge_sort_inc(Arr, mid + 1, right);
        merge(Arr, left, mid, right);
    }
}

然后在main函数中,当你在main中调用merge_sort_inc函数时:

merge_sort_inc(Array, 0, size-1); // change size to size-1

OT,你下面的代码没有错:

    while (i < n_l)
    {
        Arr[k] = Arr_l[i];
        i++;
        k++;
    }

    while (j < n_r)
    {
        Arr[k] = Arr_r[j];
        j++;
        k++;
    }

但您可以将k++ 带到条件末尾以将一行代码限制为:

    while (i < n_l)
    {
        Arr[k] = Arr_l[i];
        i++;
    }

    while (j < n_r)
    {
        Arr[k] = Arr_r[j];
        j++;
    }
    k++;

完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void print_arr(int Arr[], int size)
{
    int i;

    for (i = 0;i < size;i++)
        printf(" %d ", Arr[i]);
}

void merge(int Arr[], int left, int mid, int right)

{
    int i, j, k; 
    int n_l = (mid - left + 1);
    int n_r = (right - mid);
    int* Arr_l = calloc(n_l , sizeof(int));
    int* Arr_r = calloc(n_r , sizeof(int));
    if (Arr_l == NULL)
        return;
    if (Arr_r == NULL)
        return;

    for (i = 0;i < n_l;i++)
        Arr_l[i] = Arr[left+i];

    for (j = 0;j < n_r;j++)
        Arr_r[j] = Arr[mid + 1 + j];

    i = 0; j = 0; k = left;

    while (i < n_l && j < n_r)
    {
        if (Arr_l[i] <= Arr_r[j])
        {
            Arr[k] = Arr_l[i];
            i++;
        }
        else
        {
            Arr[k] = Arr_r[j];
            j++;
        }
        k++;
    }

    while (i < n_l)
    {
        Arr[k] = Arr_l[i];
        i++;
        k++;
    }

    while (j < n_r)
    {
        Arr[k] = Arr_r[j];
        j++;
        k++;
    }
    free(Arr_l);
    free(Arr_r);
} 

void merge_sort_inc(int Arr[], int left, int right) {
    if (left < right)
    {   
        int mid = left + (right - left) / 2;
        merge_sort_inc(Arr, left, mid);
        merge_sort_inc(Arr, mid + 1, right);
        merge(Arr, left, mid, right);
    }
}


int main()
{

    int i;
    time_t t;
    srand((unsigned)time(&t));
    int Array[10];
    int size = sizeof(Array) / sizeof(int);
    for (i = 0;i < size;i++)
        Array[i] = rand() % 100; // should use % instead of / to have smaller value to see easily
    printf(" The unsorted Arrar is : \n\n");
    print_arr(Array, size);

    printf("\n\n The sorted Array is : \n ");

    merge_sort_inc(Array, 0, size-1);

    print_arr(Array, size);
    return 0;
}

测试的输出:

 The unsorted Arrar is :                                                                                                

 60  32  71  35  93  91  29  80  78  47                                                                                 

 The sorted Array is :                                                                                                  
  29  32  35  47  60  71  78  80  91  93 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-26
    • 2014-09-07
    • 2014-11-21
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多