【问题标题】:Combining MergeSort with Insertion sort to make it more efficient将 MergeSort 与 Insertion 排序相结合,提高效率
【发布时间】:2013-02-10 00:36:12
【问题描述】:

所以我有一个 MergeSort 算法,我想将 MergeSort 与插入排序结合起来以减少合并的开销,问题是如何?我想使用插入排序对段进行排序,然后合并。

 public class mergesorttest{
    public static void main(String[]args){
        int d[]= {10,2,3,4,5,6,5,4,3,5,6,7,1};
        mergeSort(d,0,d.length);
        for(int x:d) System.out.print(x+" "); 
        System.out.println(); 
    }

static void mergeSort(int f[],int lb, int ub){
    //termination reached when a segment of size 1 reached -lb+1=ub
    if(lb+1<ub){
        int mid = (lb+ub)/2;
        mergeSort(f,lb,mid);
        mergeSort(f,mid,ub);
        merge(f,lb,mid,ub);
    }
}

static void merge (int f[],int p, int q, int r){
    //p<=q<=r
    int i =p; int j = q; 
    //use temp array to store merged sub-sequence
    int temp[] = new int[r-p]; int t = 0; 
    while(i<q && j<r){
        if(f[i]<=f[j]){
            temp[t] =f[i]; 
            i++;t++;
        }
        else{
            temp[t] = f[j];
            j++;
            t++;
        }

        //tag on remaining sequence
        while(i<q){
            temp[t] = f[i];
            i++;
            t++;

        }
        while(j<r){
            temp[t]=f[j];
            j++;
            t++;
        }
        //copy temp back to f
        i=p;t=0;
        while(t<temp.length){
            f[i]=temp[t];
            i++;
            t++;
        }
        }
}
}

public static void insertion_srt(int array[], int n, int b){
  for (int i = 1; i < n; i++){
  int j = i;
  int B = array[i];
  while ((j > 0) && (array[j-1] > B)){
  array[j] = array[j-1];
  j--;
  }
  array[j] = B;
  }
  }

【问题讨论】:

    标签: java mergesort insertion-sort


    【解决方案1】:

    合并会自动对元素进行排序。但是,当列表低于某个阈值时,可以使用插入排序进行排序:

    static final int THRESHOLD = 10;
    static void mergeSort(int f[],int lb, int ub){
        if (ub - lb <= THRESHOLD)
            insertionSort(f, lb, ub);
        else
        {
            int mid = (lb+ub)/2;
            mergeSort(f,lb,mid);
            mergeSort(f,mid,ub);
            merge(f,lb,mid,ub);
        }
    }
    

    除此之外的任何操作(除了稍微调整阈值)都会增加归并排序所花费的时间。

    虽然归并排序是 O(n log n) 而插入排序是 O(n2),但插入排序具有更好的常数,因此在非常小的数组上速度更快。 Thisthisthisthis 是我发现的一些相关问题。

    【讨论】:

    • 这是一个很好的答案,尽管它有助于深入了解大 O 理论并解释最佳情况/最坏情况/平均情况。
    • 值得一提的是,这正是 JDK 内置排序的工作原理 - 对于数组 7 它执行合并排序。
    • 我认为Collections.sort() 使用快速排序来处理更大的集合。
    • @bdares Collections.sort + Arrays.sort 对象 = 合并排序。 Arrays.sort 关于原语 = 快速排序
    • @VisionarySoftwareSolutions 我刚刚检查了我提供的链接,它说明了它使用的算法。但是,如果您愿意 - Collections sourceArrays source。请注意,如果您有 JDK 和适当的 IDE (NetBeans),打开源代码就像 Ctrl+Click 一样简单。
    【解决方案2】:
    public static final int K = 5;
    
    public static void insertionSort(int A[], int p, int q) {
        for (int i = p; i < q; i++) {
            int tempVal = A[i + 1];
            int j = i + 1;
            while (j > p && A[j - 1] > tempVal) {
                A[j] = A[j - 1];
                j--;
            }
            A[j] = tempVal;
        }
        int[] temp = Arrays.copyOfRange(A, p, q +1);
        Arrays.stream(temp).forEach(i -> System.out.print(i + " "));
        System.out.println();
    }
    
    public static void merge(int A[], int p, int q, int r) {
        int n1 = q - p + 1;
        int n2 = r - q;
        int[] LA = Arrays.copyOfRange(A, p, q +1);
        int[] RA = Arrays.copyOfRange(A, q+1, r +1);
        int RIDX = 0;
        int LIDX = 0;
        for (int i = p; i < r - p + 1; i++) {
            if (RIDX == n2) {
                A[i] = LA[LIDX];
                LIDX++;
            } else if (LIDX == n1) {
                A[i] = RA[RIDX];
                RIDX++;
            } else if (RA[RIDX] > LA[LIDX]) {
                A[i] = LA[LIDX];
                LIDX++;
            } else {
                A[i] = RA[RIDX];
                RIDX++;
            }
        }
    }
    
    public static void sort(int A[], int p, int r) {
        if (r - p > K) {
            int q = (p + r) / 2;
            sort(A, p, q);
            sort(A, q + 1, r);
            merge(A, p, q, r);
        } else {
            insertionSort(A, p, r);
        }
    }
    
    public static void main(String string[]) {
        int[] A = { 2, 5, 1, 6, 7, 3, 8, 4, 9 };
        sort(A, 0, A.length - 1);
        Arrays.stream(A).forEach(i -> System.out.print(i + " "));
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-08
      • 2020-06-24
      • 2010-10-26
      • 1970-01-01
      • 1970-01-01
      • 2021-12-04
      • 1970-01-01
      相关资源
      最近更新 更多