为什么递归合并排序函数显示O(n ^ 2)时间复杂度

时间:2018-02-16 08:05:04

标签: performance sorting recursion time-complexity mergesort

我尝试递归地实现合并排序,不幸的是,它似乎显示O(n ^ 2)复杂度而不是期望的O(nlogn)。 这是代码,首先我调用一个驱动程序方法(在这里创建临时数组,因此它不需要为每个递归调用重新初始化):

<select [ngModel]="object">
  <option *ngFor="let object of objects;let i= index;" [value]="object.value" selected="i==0">{{object.name}}</option>
</select>

一旦处理了所有驱动程序业务,就会调用mergeSortRecusive(一旦子数组达到一定大小,我就切换到插入排序。在这种情况下,INSERTTHRESHOLD设置为10):

public static <T> void mergesort(ArrayList<T> list, Comparator<? super T> comparator) {

        // Create and initialize a temporary ArrayList to be passed through the
        // recursive method.
        ArrayList<T> temp = new ArrayList<T>();
        for (int i = 0; i < list.size(); i++) {
            temp.add(null);
        }
        mergeSortRecursive(list,temp, 0, list.size()-1, comparator);

    }

最后,一旦一切都很好并且分开了,就会调用merge函数将它们全部重新组合在一起:

private static <T> void mergeSortRecursive (ArrayList<T> list, ArrayList<T> temp, int left, int right,  Comparator<? super T> comparator) {
        // If ArrayList size is less than the set threshold call the insertSort
        // method and return results instead continuing to call the recursive method.
        if(right - left < INSERTTHRESHOLD) {
        insertionSort(list, left, right, comparator);
        }

        // Find mid point in ArrayList biased on size of array.
        int mid = (left + right) / 2;

        // Recursively call the mergeSortRecursive method passing the first half of the
        // ArrayList.
        mergeSortRecursive(list,temp, left, mid, comparator);
        // Recursively call the mergeSortRecursive method passing the second half of the
        // ArrayList.
        mergeSortRecursive(list,temp, mid+1, right, comparator);

        // Merge the two half array lists back together and return the results.
        merge(list,temp, left, mid+1, right, comparator);


    }

这是时间图:

time graph

这是n ^ 2的平均时间:

time over n^2

这里的时间超过n * log(n):

time over n*log(n)

那么为什么要把这件事拿这么久?

1 个答案:

答案 0 :(得分:0)

您可以在系统上测试此示例代码吗?它是一个优化的自顶向下合并排序,它在int(primitive)上运行。这个例子在大约1.2秒内排序10,000,000个整数。对于你的例子,我想知道所有这些set调用的开销(做这些释放并分配内存?),以及arraylist(指向对象的指针数组)的开销。

package jsorttd;
import java.util.Random;

public class jsorttd {
    static void MergeSort(int[] a)          // entry function
    {
        if(a.length < 2)                    // if size < 2 return
            return;
        int[] b = new int[a.length];
        MergeSortAtoA(a, b, 0, a.length);
    }

    static void MergeSortAtoA(int[] a, int[] b, int ll, int ee)
    {
        if(ee - ll > 1) {
            int rr = (ll + ee)>>1;          // midpoint, start of right half
            MergeSortAtoB(a, b, ll, rr);
            MergeSortAtoB(a, b, rr, ee);
            Merge(b, a, ll, rr, ee);        // merge b to a
        }
    }

    static void MergeSortAtoB(int[] a, int[] b, int ll, int ee)
    {
        if(ee - ll > 1) {
            int rr = (ll + ee)>>1;          // midpoint, start of right half
            MergeSortAtoA(a, b, ll, rr);
            MergeSortAtoA(a, b, rr, ee);
            Merge(a, b, ll, rr, ee);        // merge a to b
        } else if((ee - ll) == 1) {         // if just one element
            b[ll] = a[ll];                  //   copy a to b
        }
    }

    static void Merge(int[] a, int[] b, int ll, int rr, int ee) {
        int o = ll;                         // b[]       index
        int l = ll;                         // a[] left  index
        int r = rr;                         // a[] right index
        while(true){                        // 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
            }
        }
    }

    public static void main(String[] args) {
        int[] a = new int[10000000];
        Random r = new Random();
        for(int i = 0; i < a.length; i++)
            a[i] = r.nextInt();
        long bgn, end;
        bgn = System.currentTimeMillis();
        MergeSort(a);
        end = System.currentTimeMillis();
        for(int i = 1; i < a.length; i++){
            if(a[i-1] > a[i]){
                System.out.println("failed");
                break;
            }
        }
        System.out.println("milliseconds " + (end-bgn));
     }
}