无法理解Merge Sort的特定C实现

时间:2017-08-20 13:54:55

标签: c algorithm sorting

我正在尝试一步一步地遵循此代码,但仍然无法理解它正在采取的某些步骤。

void merge (int *a, int n, int m) {
    int i, j, k;
    int *x = malloc(n * sizeof (int));
    for (i = 0, j = m, k = 0; k < n; k++) {
        x[k] = j == n      ? a[i++]
             : i == m      ? a[j++]
             : a[j] < a[i] ? a[j++]
             :               a[i++];
    }
    for (i = 0; i < n; i++) {
        a[i] = x[i];
    }
    free(x);
}

void merge_sort (int *a, int n) {
    if (n < 2)
        return;
    int m = n / 2;
    merge_sort(a, m);
    merge_sort(a + m, n - m);
    merge(a, n, m);
}

这是一个简单的例子,您可以看到问题所在。它正在对整数数组{4,3,2,1}进行排序。

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

void merge (int *a, int n, int m) {
    int i, j, k;
    int *x = malloc(n * sizeof (int));
    for (i = 0, j = m, k = 0; k < n; k++) {
        x[k] = j == n      ? a[i++]
             : i == m      ? a[j++]
             : a[j] < a[i] ? a[j++]
             :               a[i++];
    }
    for (i = 0; i < n; i++) {
        a[i] = x[i];
    }
    free(x);
}

void merge_sort (int *a, int n) {
    if (n < 2)
        return;
    int m = n / 2;
    int g;
    printf("a before merge_sort(a,m) %i\n",a);
    printf("m %i\n",m);
    printf("n %i\n",n);
    printf("\n");
    for(g=0;g<m;++g) printf("%i\n", a[g]);
    merge_sort(a, m);
    printf("a after merge_sort(a,m) %i\n",a);
    printf("m %i\n",m);
    printf("n %i\n",n);
    printf("\n");
    for(g=0;g<m;++g) printf("%i\n", a[g]);
    merge_sort(a + m, n - m);
    printf("a after merge_sort(a+m, n-m) %i\n",a);
    printf("m %i\n",m);
    printf("n %i\n",n);
    printf("\n");
    for(g=0;g<m;++g) printf("%i\n",a[g]);
    merge(a, n, m);
    printf("a after merge(a,n,m) %i\n ",a);
    printf("m %i\n",m);
    printf("n %i\n",n);
    for(g=0;g<m;++g) printf("%i\n",a[g]);
}

int main(){
    int test[4] = {4,3,2,1};
    int i;
    merge_sort(&test[0],4);
    printf("\nFinal result:\n");
    for(i=0;i<4;++i){
        printf("%i ",test[i]);
    }
    printf("\n");
}

这是输出。

Begin of if
End of if(no return)

a before merge_sort(a,m) 0xbfadcebc
m 2
n 4

4
3

Begin of if
End of if(no return)

a before merge_sort(a,m) 0xbfadcebc
m 1
n 2

4

Begin of if

a after merge_sort(a,m) 0xbfadcebc
m 1
n 2

4

Begin of if

a after merge_sort(a+m, n-m) 0xbfadcebc
m 1
n 2

4

a after merge(a,n,m) 0xbfadcebc
 m 1
n 2

3

a after merge_sort(a,m) 0xbfadcebc
m 2
n 4

3
4

Begin of if
End of if(no return)

a before merge_sort(a,m) 0xbfadcec4
m 1
n 2

2

Begin of if

a after merge_sort(a,m) 0xbfadcec4
m 1
n 2

2

Begin of if

a after merge_sort(a+m, n-m) 0xbfadcec4
m 1
n 2

2

a after merge(a,n,m) 0xbfadcec4
 m 1
n 2

1

a after merge_sort(a+m, n-m) 0xbfadcebc
m 2
n 4

3
4

a after merge(a,n,m) 0xbfadcebc
 m 2
n 4

1
2

Final result:
1 2 3 4 

令我困惑的是:

Begin of if

a after merge_sort(a+m, n-m) 0xbfadcebc
m 1
n 2

4

a after merge(a,n,m) 0xbfadcebc
 m 1
n 2

3

我希望有一个+ m可以将一个地址从0xbfadcebc更改为其他地方,但它只会再次产生数字4作为输出。这就好像合并(a + m,n-m)没有任何效果,产生的效果就像我写了合并(a,n-m)一样。

此外,merge(a,n,m)不是递归函数,所以我只希望函数在运行后结束。 我不明白这个:

a after merge_sort(a,m) 0xbfadcebc
m 2
n 4

3
4

...可以是合并后的下一步(a,n,m)。

1 个答案:

答案 0 :(得分:0)

评论代码:

/* a = ptr to sub-array */
/* 0 = starting index */
/* m = mid point index */
/* n = ending index */
/* left  half indices = 0 to m-1 */
/* right half indices = m to n   */
void merge (int *a, int n, int m) {
    int i, j, k;
    int *x = malloc(n * sizeof (int)); /* allocate temp array */
    for (i = 0, j = m, k = 0; k < n; k++) {
        x[k] = j == n      ? a[i++]    /* if end of right, copy left */
             : i == m      ? a[j++]    /* if end of left, copy right */
             : a[j] < a[i] ? a[j++]    /* if right < left, copy right */
             :               a[i++];   /* else (left <= right), copy left */
    }
    for (i = 0; i < n; i++) {          /* copy x[] back into a[] */
        a[i] = x[i];
    }
    free(x);                           /* free temp array */
}

/* a = ptr to sub-array */
/* n = size == ending index of sub-array */     
void merge_sort (int *a, int n) {
    if (n < 2)                         /* if < 2 elements nothing to do */
        return;
    int m = n / 2;                     /* m = mid point index */
    merge_sort(a, m);                  /* sort a[0] to a[m-1] */
    merge_sort(a + m, n - m);          /* sort a[m] to a[n-1] */
    merge(a, n, m);                    /* merge the two halves */
}