algorithm - 迭代/非递归合并排序

标签 algorithm sorting mergesort

我正在尝试迭代合并排序,但在输入长度不是 2^x 的情况下卡住了。

像 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));
    }
}

当输入长度为 2^x 时,它工作正常。

还有没有更好的实现迭代版本的方法,这个看起来很乱

最佳答案

自底向上合并排序的 C++ 示例。 a[] 是要排序的数组,b[] 是临时数组。它包括检查合并 channel 的数量,如果 channel 数量为奇数,则进行适当的交换,以便最终在 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);
}

关于algorithm - 迭代/非递归合并排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37366365/

相关文章:

java - 大数的质因数分解

python - 打破 Python 排序中的联系

java - 按另一个对象排序

c++ - 合并排序无法在流程结束时合并零件

python - 使用python从图像中提取线条

algorithm - 路由器如何组织其路由表?

c++ - 合并排序实现给出运行时错误?

c++ - 合并排序无法正常工作

c++ - <algorithm> 是否定义了宏 X?

python - 如何在 Python 中对 sql 生成的元组数组进行排序