Слияние Сортировка на основе учебника CLRS

Следующий код соответствует CLRS ( Corman, Leiserson, Rivest, Stein - «Введение в алгоритмы», ), который должен выполнять сортировку слиянием.

Я не могу определить ошибку, которая происходит, хотя я знаю, что что-то не так происходит в функции mergesort() . Я думаю, что merge() функционально нетронутым.

/* Merge sort as per CLRS */
#include 
#include 

void merge(int *a,int p,int q,int r){
int n1 = q - p + 1;
int n2 = r - q;
int* l = malloc((n1+1)*sizeof(int));
int* ri = malloc((n2+1)*sizeof(int));
int i,j;
for(i = 0 ; i < n1 ; i++)
    l[i] = a[p+i-1];
for(i = 0 ; i < n2 ; i++)
    ri[i] = a[q+i];
l[n1] = 9999;
ri[n2] = 9999;
i = 0;
j = 0;
int k;
for ( k = p ; k <= r ; k++){
    if( l[i] < ri[j] ){
        a[k] = l[i];
        i++;
    }
    else{
        a[k] = ri[j];
        j++;
    } 
}
}

void mergeSort(int* a,int p,int r){
if( p < r){

    int q = ( p + r )/2;
    mergeSort(a,p,q);
    mergeSort(a,p+1,r);
    merge(a,p,q,r);
}

else return;

}

int main(int argc, char* argv[]){
int a[] = {9,21,4,15,1,3};

mergeSort(a,0,5);

int i;
for( i = 0 ; i < 6 ; i++){
    printf("%d ",a[i]);
}
return 0;

}
1
nl ja de
Так в чем проблема? Это дает вам неправильный результат?
добавлено автор Tudor, источник
else return; в mergeSort() является избыточным; функция будет возвращаться в любом случае (и если она выполняет if ), она выполняет неявный return; после возврата else; ).
добавлено автор Jonathan Leffler, источник
добавлено автор Arpit, источник

2 ответы

В коде mergeSort() у вас есть:

int q = ( p + r )/2;
mergeSort(a,p,q);
mergeSort(a,p+1,r);
merge(a,p,q,r);

Я думаю, что второй mergeSort должен быть mergeSort (a, q + 1, r); , не так ли?

Это не зависит от анализа Даниэль Фишер .


В merge() вы выделяете два массива. Вы не освобождаете эти массивы. Это утечка памяти. Вы также должны проверить, что распределения были успешными.

3
добавлено
слияние (а, р + 1, г); должен быть mergeSort (a, q + 1, r); правильно?
добавлено автор Virtually Real, источник
@VirtualReal: Я думаю, что это то, что я сказал ... Я процитировал код в вопросе (потому что этот вопрос имеет привычку морфинга по мере того, как ответ просачивается), и предположим, что правильный вызов - это то, что вы сказали ,
добавлено автор Jonathan Leffler, источник
@Krishna: Я предлагаю вам создать подходящий массив для merge() для работы, например int x [] = {1, 3, 5, 7, 2, 4, 5, 8, 10}; и назовите его: merge (x, 0, 4, 8); (я думаю, это ваше соглашение о вызове) и посмотрите, что произойдет. Вы можете пройти через него с помощью отладчика. Если это работает, попробуйте другие массивы: int x2 [] = {99, 100, 101, 0, 1, 2, 3}; и убедитесь, что они правильно объединены. Когда вы убедитесь, что merge() работает правильно, вы можете приступить к работе над mergeSort() .
добавлено автор Jonathan Leffler, источник
Даже после исправления «p + 1» до «q + 1», я не получаю надлежащего вывода. Наверное, я не должен пытаться делать сортировку на месте. Это проблема?
добавлено автор Krishna, источник
void merge(int *a,int p,int q,int r){
    int n1 = q - p + 1;
    int n2 = r - q;
    int* l = malloc((n1+1)*sizeof(int));
    int* ri = malloc((n2+1)*sizeof(int));
    int i,j;
    for(i = 0 ; i < n1 ; i++)
        l[i] = a[p+i-1];
    for(i = 0 ; i < n2 ; i++)
        ri[i] = a[q+i];

Вы пишете элементы из индекса p-1 через индекс q-1 в l , а элементы из индекса q через r-1 в ri . Если p == 0 , вы получаете доступ за пределы.

Вы хотите, однако, отсортировать элементы из индекса p через r .

void merge(int *a,int p,int q,int r){
    int n1 = q - p + 1;
    int n2 = r - q;
    int* l = malloc((n1)*sizeof(int));
    int* ri = malloc((n2)*sizeof(int));
    int i,j;
    for(i = 0 ; i < n1 ; i++)
        l[i] = a[p+i];
    for(i = 0 ; i < n2 ; i++)
        ri[i] = a[q+i+1];

Кроме того, вы должны проверить, меньше ли индексы, i и j , чем соответствующий конечный индекс n1 resp. n2 , и когда кто-то достигнет конца своей части, скопируйте оставшиеся из другой части в массив. Значительное значение защиты страшно, если массив содержит большие записи.

while(i < n1 && j < n2) {
    if (ri[j] < l[i]) {
        a[k++] = ri[j++];
    } else {
        a[k++] = l[i++];
    }
}
while(i < n1) {
    a[k++] = l[i++];
}
while(j < n2) {
    a[k++] = ri[j++];
}
2
добавлено