Iterative/ Non-Recursive Merge Sort

て烟熏妆下的殇ゞ 提交于 2019-12-11 13:41:41

问题


I was trying iterative merge sort , but am stuck at at conditions when input length is not 2^x.

like int[] A ={4,5,1,254,66,75,12,8,65,4,87,63,53,8,99,54,12,34};

public class MergeSort {
    public static void sort(int[] A) {
        System.out.println("Log(A.len):"+log(A.length, 2));

        for (int i = 0; i < log(A.length, 2); i++) { //log A.len
            int r = 2 << i; //2^i
            int mid = r >>> 1;
            for (int j = 0; j+r < A.length; j = j + r) {
                System.out.print("offset:" + j + " mid:" + (j + mid) + " r:" + (j + r));
                merge(A, j, (j + mid), (j + r));
            }
        }
    }

    public static void merge(int[] A, int offset, int mid, int n) {
        mid = mid - offset;
        n = n - offset;
        int[] L = new int[mid];
        int[] R = new int[n - mid];
        for (int i = 0; i < mid; i++) {
            L[i] = A[i + offset];
            R[i] = A[mid + i + offset];
        }
        System.out.print("\nL:");
        print_array(L);
        System.out.print("\nR:");
        print_array(R);

        int l = 0;
        int r = 0; //left right pointer
        int k = offset;
        while (l < mid && r < mid) {
            if (L[l] < R[r]) {
//                System.out.println("in left");
                A[k] = L[l];
                l++;
            } else {
//                System.out.println("in right");
                A[k] = R[r];
                r++;
            }
            k++;
        }
        while (l < mid) {
            A[k] = L[l];
            l++;
            k++;
        }
        while (r < mid) {
            A[k] = R[r];
            r++;
            k++;
        }

        System.out.print("\nA:");
        print_array(A);
        System.out.print("\n\n");

    }


    public static void main(String[] args) {
        int[] A ={4,5,1,254,66,75,12,8,65,4,87,63,53,8,99,54,12,34};
        sort(A);

    }

    public static void print_array(int[] A) {
        for (int i = 0; i < A.length; i++) {
            System.out.print(A[i] + " ");
        }
    }

    static int log(int x, int base) {
        return (int) (Math.log(x) / Math.log(base));
    }
}

It works fine when input length is 2^x.

Also is there any better way to implement iterative version , this looks a lot messy.


回答1:


C++ example of bottom up merge sort. a[] is array to sort, b[] is temp array. It includes a check for number of merge passes and swaps in place if the number of passes would be odd, in order to end up with the sorted data in a[].

void BottomUpMerge(int a[], int b[], size_t ll, size_t rr, size_t ee);
void BottomUpCopy(int a[], int b[], size_t ll, size_t rr);
size_t GetPassCount(size_t n);

void BottomUpMergeSort(int a[], int b[], size_t n)
{
size_t s = 1;                               // run size 
    if(GetPassCount(n) & 1){                // if odd number of passes
        for(s = 1; s < n; s += 2)           // swap in place for 1st pass
            if(a[s] < a[s-1])
                std::swap(a[s], a[s-1]);
        s = 2;
    }
    while(s < n){                           // while not done
        size_t ee = 0;                      // reset 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
        s <<= 1;                            // double the run size
    }
}

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)
            do                              //   else copy rest of right run
                b[o++] = a[r++];
            while(r < ee);
            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)
            do                              //   else copy rest of left run
                b[o++] = a[l++];
            while(l < rr);
            break;                          //     and return
        }
    }
}

void BottomUpCopy(int a[], int b[], size_t ll, size_t rr)
{
    do                                      // copy left run
        b[ll] = a[ll];
    while(++ll < rr);
}

size_t GetPassCount(size_t n)               // return # passes
{
    size_t i = 0;
    for(size_t s = 1; s < n; s <<= 1)
        i += 1;
    return(i);
}


来源:https://stackoverflow.com/questions/37366365/iterative-non-recursive-merge-sort

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!