merge_sort using vectors works well with less than 9 inputs

前端 未结 1 965
遥遥无期
遥遥无期 2021-01-26 03:48

Somehow I implemented Merge sort using vectors, the problem is: It works correctly with less than 9 inputs, but with 9 or more inputs it does something which I don\'t understand

相关标签:
1条回答
  • 2021-01-26 04:09

    Here is a pair of merge sort examples, somewhat optimized, and perhaps a bit more than what would be expected from a student.

    The top example is a top down merge sort. a[] is the array to be sorted, b[] is a temp array the same size as a[]. Copying data is avoided via a pair of recursive functions that alternate the direction of the merge depending on the level of recursion.

    The bottom example is a bottom up merge sort. Note the sorted array can end up in either a[] or b[]. This can be avoided by calculating the number of passes and if the number of passes is odd, swap in place for the first pass.

    Both sort examples use two arrays and merge using indexes. The main difference is top down uses recursion to repeatedly split pairs of indexes until the indexes represent a run size of 1, where it then starts the actual merge process, while bottom up skips this step and just starts off with a run size of 1 and starts merging immediately. Most of the time is spent merging, so the extra overhead of recursively generating indexes is small compared to the total time it takes to sort.

    top down merge sort

    int * TopDownMergeSort(int a[], int b[], size_t n)
    {
        if(n < 2)                           // if size < 2 return
            return a;
        TopDownSplitMergeAtoA(a, b, 0, n);
        return a;
    }
    
    void TopDownSplitMergeAtoA(int a[], int b[], size_t ll, size_t ee)
    {
        if((ee - ll) == 1)                  // if size == 1 return
            return;
        size_t rr = (ll + ee)>>1;           // midpoint, start of right half
        TopDownSplitMergeAtoB(a, b, ll, rr);
        TopDownSplitMergeAtoB(a, b, rr, ee);
        TopDownMerge(b, a, ll, rr, ee);     // merge b to a
    }
    
    void TopDownSplitMergeAtoB(int a[], int b[], size_t ll, size_t ee)
    {
        if((ee - ll) == 1){                 // if size == 1 copy a to b
            b[ll] = a[ll];
            return;
        }
        size_t rr = (ll + ee)>>1;           // midpoint, start of right half
        TopDownSplitMergeAtoA(a, b, ll, rr);
        TopDownSplitMergeAtoA(a, b, rr, ee);
        TopDownMerge(a, b, ll, rr, ee);     // merge a to b
    }
    
    void TopDownMerge(int a[], int b[], size_t ll, size_t rr, size_t ee)
    {
        size_t o = ll;                          // b[]       index
        size_t l = ll;                          // a[] left  index
        size_t r = rr;                          // a[] right index
    
        while(1){                               // merge data
            if(a[l] <= a[r]){                   // if a[l] <= a[r]
                b[o++] = a[l++];                //   copy a[l]
                if(l < rr)                      //   if not end of left run
                    continue;                   //     continue (back to while)
                while(r < ee){                  //   else copy rest of right run
                    b[o++] = a[r++];
                }
                break;                          //     and return
            } else {                            // else a[l] > a[r]
                b[o++] = a[r++];                //   copy a[r]
                if(r < ee)                      //   if not end of right run
                    continue;                   //     continue (back to while)
                while(l < rr){                  //   else copy rest of left run
                    b[o++] = a[l++];
                }
                break;                          //     and return
            }
        }
    }
    

    bottom up merge sort

    int * BottomUpMergeSort(int a[], int b[], size_t n)
    {
        for(size_t s = 1; s < n; s <<= 1){      // s = run size
            size_t ee = 0;                      // init end index
            while(ee < n){                      // merge pairs of runs
                size_t ll = ee;                 // ll = start of left  run
                size_t rr = ll+s;               // rr = start of right run
                if(rr >= n){                    // if only left run
                    rr = n;
                    BottomUpCopy(a, b, ll, rr); //   copy left run
                    break;                      //   end of pass
                }
                ee = rr+s;                      // ee = end of right run
                if(ee > n)
                    ee = n;
                BottomUpMerge(a, b, ll, rr, ee);
            }
            std::swap(a, b);                    // swap a and b ptrs
        }
        return a;                               // return sorted array
    }
    
    void BottomUpCopy(int a[], int b[], size_t ll, size_t rr)
    {
        while(ll < rr){                         // copy left run
            b[ll] = a[ll];
            ll++;
        }
    }
    
    void BottomUpMerge(int a[], int b[], size_t ll, size_t rr, size_t ee)
    {
        size_t o = ll;                          // b[]       index
        size_t l = ll;                          // a[] left  index
        size_t r = rr;                          // a[] right index
    
        while(1){                               // merge data
            if(a[l] <= a[r]){                   // if a[l] <= a[r]
                b[o++] = a[l++];                //   copy a[l]
                if(l < rr)                      //   if not end of left run
                    continue;                   //     continue (back to while)
                while(r < ee){                  //   else copy rest of right run
                    b[o++] = a[r++];
                }
                break;                          //     and return
            } else {                            // else a[l] > a[r]
                b[o++] = a[r++];                //   copy a[r]
                if(r < ee)                      //   if not end of right run
                    continue;                   //     continue (back to while)
                while(l < rr){                  //   else copy rest of left run
                    b[o++] = a[l++];
                }
                break;                          //     and return
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题