Merge Sort: необходимост от копиране на елементи от временен масив

Опитвах се да анализирам mergesort, но ме порази странен бъг. това е моят код:

int merge(int *a,int st,int mid,int en)
{
    int i,j,l,m;
    i = st;
    l = st;
    m = mid + 1;
    while((l<=mid) && (m <= en))
    {
        if(a[l] <= a[m])
        {
            temp[i] = a[l];
            l++;
            i++;
        }
        else
        {
            temp[i] = a[m];
            m++;
            i++;
        }
    }
    if(l <= mid)
    {
        for(j=l;j<=mid;j++)
        {
            temp[i] = a[j];
            i++;
        }
    }
    else 
    {
        for(j=m;j<=en;j++)
        {
            temp[i] = a[j];
            i++;
        }
    }
    for(j=st;j<=en;j++) // ??
        a[j] = temp[j];  // ??
}

void mergesort(int *a,int st,int en)
{
    int mid;
    if(st<en)
    {
        mid = (st+en)/2;
        mergesort(a,st,mid);
        mergesort(a,mid+1,en);
        merge(a,st,mid,en);
    }
}

int main()
{
    int i,n;
    scanf("%d",&n);
    for(i=0;i<n;i++)
        scanf("%d",&a[i]);
    mergesort(a,0,n-1);
    for(i=0;i<n;i++)
        printf("%d\n",temp[i]);
    getch();
    return 0;
}

Използвам типичен код за сортиране чрез сливане. Изправен съм пред проблем да разбера защо е необходимо да копирам съдържанието от временния масив в основния масив, за да получа правилния изход. Опитах това на следния вход: 5 (брой термини) ,
4 4 5 3 2

И получавам изход като: 3 2 4 4 5 без да копирам съдържанието от временния масив в основния масив и ако направя копирането с помощта на цикъла „коментиран“, изходът е наред, т.е. 2 3 4 4 5. Аз съм просто не получавам, защо се случва това?


person Himanshu Kansal    schedule 06.01.2014    source източник
comment
Разберете функцията за сливане (и начина, по който се използва тук: рекурсия) и ще получите отговора.   -  person Rafed Nole    schedule 06.01.2014


Отговори (1)


Копието е необходимо, тъй като копирането се извършва във функцията за сливане, а не във функцията за сортиране по сливане. Функцията за сливане трябва да се извиква отново и отново рекурсивно; така че временният масив ще продължи да се променя.

Трябва да поставите частично сортираната част от оригиналния масив в оригиналния масив при всяко извикване на mergesort. Тази частично сортирана част всъщност е временният масив.

person Rafed Nole    schedule 06.01.2014