【问题标题】:Why is QuickSort so much slower than BubbleSort?为什么 QuickSort 比 BubbleSort 慢这么多?
【发布时间】:2013-02-01 08:35:33
【问题描述】:

我想知道为什么我的 quickSort 这么慢。对以下数组进行排序需要 10-20 秒。冒泡排序(如下所示)会自动完成。

public static void quickSort(int[] tab, int lowIndex, int highIndex) {
if (tab == null || tab.length == 0) {
    return;
}

int i = lowIndex;
int j = highIndex;

int pivot = tab[lowIndex + (highIndex - lowIndex) / 2];

while (i <= j) {
    while (tab[i] < pivot) {
    i++;
    }
    while (tab[j] > pivot) {
    j--;
    }

    if (i <= j) {
    int c = tab[i];
    tab[i] = tab[j];
    tab[j] = c;
    i++;
    j--;
    }

    if (lowIndex < j) {
    quickSort(tab, lowIndex, j);
    }
    if (i < highIndex) {
    quickSort(tab, i, highIndex);
    }
}

}

public static void bubbleSort(int[] arr) {
int n = arr.length - 1;
while (n >= 1) {
    for (int i = 0; i < n; i++) {
    if (arr[i] > arr[i + 1]) {
        int c = arr[i];
        arr[i] = arr[i + 1];
        arr[i + 1] = c;
    }
    }
    n--;
}
}

public static void main(String[] args) {
int[] t = new int[] { 5, 1, 33, 13, 21, 2, 12, 4,
    2, 3, 53, 2, 125, 23, 53, 523, 5, 235, 235, 235, 23, 523, 1,
    2, 41, 2412, 412, 4, 124, 1, 241, 24, 1, 43, 6, 346, 457, 56,
    74, 5, 3, 5, 1, 33, 13, 21, 2, 12, 4,
    2, 3, 53, 2, 125, 23, 53, 523, 5, 235, 235, 235, 23, 523, 1,
    2, 41, 2412, 412, 4, 124, 1, 241, 24, 1, 43, 6, 346, 457, 56,
    74, 5, 3, 74, 5, 3, 5, 1, 33, 13, 21, 2, 12, 4,
    2, 3, 53, 2, 125, 23, 53, 523, 5, 235, 235, 235, 23, 523, 1,
    2, 41, 2412, 412, 4, 124, 1, 241, 24, 1, 43, 6, 346, 457, 56,
    74, 5, 3 };

【问题讨论】:

  • 对于小型数据集,快速排序可能看起来较慢,因为您的快速排序实现包含递归调用。
  • 冒泡排序的最坏情况复杂度是 n^2。快速排序的工作情况复杂度为 n*ln(n)。这些是最坏的情况,它没有说明个别情况。你的数据有多随机,有多大? “自动”是什么意思?
  • 对于我的代码中的数组,快速排序时间约为 15 秒,而冒泡排序不到 1 秒。
  • @bmorris591 代码示例似乎包含一些示例数据。
  • 您的quicksort 似乎不正确。递归调用不应出现在while (i &lt;= j) 循环内。除此之外可能还有其他问题 - 你应该真正看看标准实现,通过谷歌存在数百万,例如:mycstutorials.com/articles/sorting/quicksort

标签: java algorithm quicksort bubble-sort


【解决方案1】:

基本上,您的冒泡排序在某种程度上被破坏了 - 使用 Darren Engwirda 在http://www.mycstutorials.com/articles/sorting/quicksort 的评论中链接到的实现,并且每次使用新创建的数组运行排序,我得到以下时间:

bash-3.1$ time java -cp bin Sort none

real    0m0.079s
user    0m0.000s
sys     0m0.015s
bash-3.1$ time java -cp bin Sort quick

real    0m0.084s
user    0m0.015s
sys     0m0.015s
bash-3.1$ time java -cp bin Sort bubble

real    0m0.115s
user    0m0.000s
sys     0m0.000s

运行这三个测试的基础设施在哪里:

private static int[] data () {
    return new int[] { ... the same data as in the OP ... };
}

public static void main(String[] args) {
    if ( args.length == 0 || args [ 0 ].equals ( "bubble" ) ) {
        for ( int i = 0; i < 1000; ++i ) {
            int[] data = data();
            bubbleSort ( data );
        }
    } else if ( args [ 0 ].equals ( "none" ) ) {
        for ( int i = 0; i < 1000; ++i ) {
            int[] data = data();
        }
    } else if ( args [ 0 ].equals ( "quick" ) ) {
        for ( int i = 0; i < 1000; ++i ) {
            int[] data = data();
            quickSort( data, 0, data.length-1 );
        }
    } else if ( args [ 0 ].equals ( "quick_op" ) ) {
        for ( int i = 0; i < 1000; ++i ) {
            int[] data = data();
            quickSort_op( data, 0, data.length-1 );
        }
    }
}

因此,正确实施的快速排序需要大约 5μs 来对数据进行排序,而冒泡排序需要大约 36μs 来对数据进行排序。对于此数据,快速排序算法的性能优于冒泡排序。

将递归调用移到循环之外意味着您的代码对数组进行排序(尽管我没有检查其中是否存在任何其他缺陷),结果如下:

bash-3.1$ time java -cp bin Sort op_quick

real    0m0.108s
user    0m0.015s
sys     0m0.015s

这仍然比冒泡排序快,但不如其他实现快 - 我认为您可能会重叠 j 和 i 并多次访问数组的某些部分。

【讨论】:

    猜你喜欢
    • 2013-06-05
    • 2019-12-05
    • 2019-06-26
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    • 2011-02-28
    • 2018-02-18
    相关资源
    最近更新 更多