views:

92

answers:

1
merge1(int low, int high, int S[], U[]) 
{ 
    int k = (high - low + 1)/2
    for q (from low to high) U[q] = S[q]
    int j = low 
    int p = low 
    int i = low + k 

    while (j <= low + k - 1) and (i <= high) do 
    { 
        if ( U[j] <= U[i] ) 
        {
            S[p] := U[j] 
            j := j+1
        } 
        else 
        { 
            S[p] := U[i] 
            i := i+1 
        } 
        p := p+1 
    } 

    if (j <= low + k - 1) 
    { 
        for q from p to high do 
        { 
            S[q] := U[j] 
            j := j+1 
        } 
    }
}


merge_sort1(int low, int high, int S[], U[]) 
{ 
    if low < high 
    { 
        int k := (high - low + 1)/2 
        merge_sort1(low, low+k-1, S, U) 
        merge_sort1(low+k, high, S, U) 
        merge1(low, high, S, U) 
    } 
}

So, basically, this is on my lecture notes. I find it quite confusing in general but I understand the biggest part of it. What I don't understand is the need of the "if (j <= low + k - 1)" part. It looks like it checks if there are any elements "left" in the left part. Is that even possible when mergesorting?

+1  A: 

When merging two sorted lists (let's call them left and right), you keep taking one item and adding it to the result list, until you run out of items in either the left or right list. This is done by the first while loop. Now you need to add the elements remaining in the left or right list to the result list. There are two options:

  • The left list is out of elements, and the right list still has some. The way the code is written here, we don't need to do anything, since the end of the S array already contains the last elements in the right list.

  • The right list is out of elements, and the left list still has some. Then we copy the remaining elements to the end of S. This is what the if at the end of merge1 does.


Regarding your question if this code is "bad": The code is correct, but I would make some changes to make it more readable:

  • Descriptive variable names.
  • Passing the midpoint which separates the left and right lists to merge1 instead of having it recalculated.
interjay
Yes. Take as an example `merge1(0, 1, {2, 1})` and walk yourself through the code.
Matthew T. Staebler
The midpoint can also be calculated by (high-low)/2, right? I am just not sure how to make sure I will not miss any values.
sebkom
@SebKom: No, (high-low)/2 is too little. Suppose there are 2 elements, so `high-low==1`, and `(high-low)/2 == 0`. If you use that to split the list, you will get 0 elements in the left list and 2 elements in the right. The same thing will happen when sorting the right list, and so on, leading to infinite recursion.
interjay
In general for this kind of thing, it's good to check what happens at the minimum interesting size. In this case that's size 2, since at the size of 1 `low==high` and the `merge_sort1` function will exit immediately.
interjay
Thanks, got it. Pretty stupid question to be honest (stupid meaning that I could have worked it out if I wasn't stuck on believing, for no reason, that the left list can't have elements left).
sebkom