修改合并排序以存储原始索引

时间:2014-01-11 10:01:44

标签: c sorting mergesort

我尝试修改合并排序以存储原始索引后修改它没有正确排序..我无法找到我出错的地方请帮我找到问题..

请在下面找到我的代码。

void merge(int a[][2],int start,int middle ,int end)
{
    int size1 = middle-start +1;
    int size2 = end-middle;
    int i,j;
    int k =start;
    int L[size1][2];
    int R[size2][2];
    //int *L = (int *)malloc(sizeof(int)*size1);
    //int *R = (int *)malloc(sizeof(int)*size2);

    // copy values from main array to temp arrays
    for(i=0 ; i<size1; i++)
    {
        L[i][1] = a[i+start][1];
        L[i][0] = a[i+start][0];
    }
    for(j=0 ; j<size2 ; j++)
    {
        R[j][1] = a[j+middle+1][1];
        R[j][0] = a[j+middle+1][0];
    }

    i=0;
    j=0;
    while(i<size1 && j<size2)
    {
        if(L[i] < R[j])
        {
            a[k][1] = L[i][1];
            a[k][0] = L[i][0];
            k++;
            i++;
        }
        else{
            a[k][1] = R[j][1];
            a[k][0] = R[j][0];
            k++;
            j++;
        }
    }
    while(i<size1)
    {
        a[k][1] = L[i][1];
        a[k][0] = L[i][0];
        i++;
        k++;
    }
    while(j<size2)
    {
        a[k][1] = R[j][1];
        a[k][0] = R[j][0];
        k++;
        j++;
    }
}

void mergeSort(int a[][2], int start , int end)
{
    if(start < end)
    {
        int middle = start + (end - start) /2;
        mergeSort(a,start, middle);
        mergeSort(a,middle+1,end);
        merge(a,start,middle,end);
    }
}

int main()
{
    int array[10][2] = {{0,55},{1,3},{2,4},{3,5},{4,6},{5,7},{6,8},{7,9},{8,10},{9,2}};
    int i;
    int len = sizeof(array)/sizeof(array[0]) - 1;
    for(i = 0 ;i <= 9; i++)
        printf("%d",array[i][1]);
    mergeSort(array,0,9);
    printf ( "\nArray after sorting:\n") ;
    printf ( "\nindex after sorting:\n") ;
    for(i = 0 ;i <= 9; i++)
        printf("%d",array[i][0]);
    printf ( "\nArray after sorting:\n") ;
    for(i = 0 ;i <= 9; i++)
        printf("%d",array[i][1]);
}

1 个答案:

答案 0 :(得分:2)

您的基本问题在于合并算法的初始while循环:

if(L[i] < R[j])

这是比较两个int [2]数组的内存地址,而不是相同的第二个插槽中保存的值,这就是你应该做的事情。

if(L[i][1] < R[j][1])

尽管如此,这可能会变得相当简单,但这是主要问题的症结所在。


指针数学版

为了补充我在这个答案中删除的注释,以下是代码的简化版本,它使用指针数学进行段拆分而不仅仅是索引。仔细查看mergeSort()的递归调用以及参数。另请注意在merge算法中使用单个临时数组和索引:

void merge(int a[][2], int mid, int len)
{
    int tmp[len][2];
    int i,j,k=0;

    // copy values from main array to temp
    memcpy(tmp, a, len*sizeof(*a));

    i=0; j=mid;
    while(i<mid && j<len)
    {
        if (tmp[i][1] < tmp[j][1])
        {
            // take from left side
            a[k][1] = tmp[i][1];
            a[k][0] = tmp[i++][0];
        }
        else
        {   // take from right side
            a[k][1] = tmp[j][1];
            a[k][0] = tmp[j++][0];
        }

        ++k; // always incremented
    }

    // one of these is skipped. the other will
    //  finish the merge algorithm
    while(i<mid)
    {
        a[k][1] = tmp[i][1];
        a[k++][0] = tmp[i++][0];
    }

    while(j<len)
    {
        a[k][1] = tmp[j][1];
        a[k++][0] = tmp[j++][0];
    }
}

void mergeSort(int a[][2], int len)
{
    if (len > 1)
    {
        int mid = len / 2;
        mergeSort(a, mid);
        mergeSort(a+mid, len-mid); // note: pointer math for right-segment
        merge(a, mid, len);
    }
}

int main()
{
    int array[10][2] = {{0,55},{1,3},{2,4},{3,5},{4,6},{5,7},{6,8},{7,9},{8,10},{9,2}};
    int i;
    int len = sizeof(array)/sizeof(array[0]);
    for(i = 0 ;i < len; i++)
        printf("%d ",array[i][1]);

    mergeSort(array, len);

    printf ( "\nIndex after sorting:\n") ;
    for(i = 0 ;i < len; i++)
        printf("%d ",array[i][0]);

    printf ( "\nArray after sorting:\n") ;
    for(i = 0 ;i < len; i++)
        printf("%d ",array[i][1]);
}

<强>输出

55 3 4 5 6 7 8 9 10 2 
Index after sorting:
9 1 2 3 4 5 6 7 8 0 
Array after sorting:
2 3 4 5 6 7 8 9 10 55