为什么我的mergeSort / shellSort比插入排序慢

时间:2015-12-31 17:20:56

标签: java algorithm

我有一个包含100000个元素的数组,我填写了0-999999的随机数字 这是我的合并排序 代码

private static void sortArray(int[] data, int low, int high)
{
    if ((high - low) >= 1)
    {
        int middle1 = (low + high) / 2;
        int middle2 = middle1 + 1;
        sortArray(data, low, middle1);
        sortArray(data, middle2, high);
        merge (data, low, middle1, middle2, high);
    }
}

private static void merge(int[] data, int left, int middle1,
                          int middle2, int right)
{
    int leftIndex = left;
    int rightIndex = middle2;
    int combinedIndex = left;
    int[] combined = new int[data.length];

    while (leftIndex <= middle1 && rightIndex <= right)
    {
        if (data[leftIndex] <= data[rightIndex]){
            combined[combinedIndex++] = data[leftIndex++];
        }
        else{
            combined[combinedIndex++] = data[rightIndex++];
        }
    }

    if (leftIndex == middle2){

        while (rightIndex <= right)
            combined[combinedIndex++] = data[rightIndex++];
    }
    else {
        while (leftIndex <= middle1)
            combined[combinedIndex++] = data[leftIndex++];
    }
    for (int i = left; i <= right; i++)
        data[i] = combined[i];

}

这是我的shellSort代码:

public static void shellSort(){

    int inner , outer , temp;
    int interval = 1;
    while(interval < arraysize/3){
        interval = interval*3+1;
    }
    while(interval > 0){
        for(outer = interval; outer<arraysize; outer++){
            inner = outer;
            temp = array[inner];
            while(inner > interval-1 && array[inner-interval] >= temp){
                array[inner] = array[inner-interval];
                inner = inner - interval;
            }
                array[inner] = temp;
        }
            interval = (interval-1)/3;
    }       
}

这是我的 insertionSort

  public  static void insertionSort(){

    for(int i = 1; i < arraysize; i++){

        int value = array[i];
        int index = i;
        while(index > 0 && value < array[index-1]){
            array[index] = array[index-1];
            index--;
        }
        array[index] = value;
    }
}

这是时间码:

    start = System.nanoTime();
    shellSort();
    end = System.nanoTime();
    System.out.println("shellsort took " + (end-start) + " nanosecs");

    start = System.nanoTime();
    sortArray(array , 0 , arraysize-1);
    end = System.nanoTime();
    System.out.println("mergesort took " + (end-start) + " nanosecs");

    start = System.nanoTime();
    insertionSort();
    end = System.nanoTime();
    System.out.println("insertionsort took " + (end-start) + " nanosecs");

时间: 炮弹拍摄了25301559纳秒 mergesort拿了41976634024纳秒 insertionsort花了2337867纳秒

4 个答案:

答案 0 :(得分:1)

很可能是因为您正在创建更多对象并具有冗余副本。我建议您对其进行分析,看看花费的时间最多。

尝试实现它而不创建如此大的数组。插入排序不会创建任何。

BTW,(low + high) / 2可能会溢出。

我建议改用(low + high) >>> 1low + (high - low) / 2

答案 1 :(得分:1)

每次使用相同的临时数组(合并[])而不是分配新的数据。

此外,insertSort的速度并不快。 InsertionSort在已经排序或完全相同的数据上非常快,因此您可能正在使用合并排序的输出(您的计时代码按原样执行),或者您的数组填充代码放入全零或东西。

答案 2 :(得分:1)

编辑:啊,是的,在对原始问题的评论中提出了一个非常好的观点:您的插入排序是对已经排序的数据进行排序。这确实应该非常快,因为它需要对阵列进行单次扫描。

Shell排序的预期性能没有对间隙的数量和大小进行一些复杂的优化,与插入排序大致相同,这与您所看到的一致。

对于mergesort,在每一步上分配一个新的巨大数组,然后复制数据就是杀死你的东西。你必须重写它来就地合并以查看实际排序的性能。

答案 3 :(得分:0)

算法具有Big-O复杂度,可根据N许多输入为您提供算法的估计运行时间

这是一个很棒的网站,列出了许多不同算法的时间和大小复杂性。

Site - http://bigocheatsheet.com/

              Best Case                        Worst Case

MergeSort          O(n log(n)) (Average)        O(n log(n)) (Average)   
ShellSort          O(n) (Good)                  O((nlog(n))^2) (Bad)   
InsertionSort      O(n) (Good)                  O(n ^ 2) (Bad)   

插入和Shell有可能更快,但在大多数情况下,mergesort应该更快。