Java 基准测试quicksort和mergesort会使mergesort更快

Java 基准测试quicksort和mergesort会使mergesort更快,java,benchmarking,quicksort,mergesort,Java,Benchmarking,Quicksort,Mergesort,我已经尝试过基准测试,出于某种原因,当在1M元素数组上尝试这两种方法时,Mergesort将其排序为0.3s,Quicksort将其排序为1.3s 我听说快速排序通常更快,因为它的内存管理,但是如何解释这些结果呢 如果这有什么不同的话,我正在运行MacBookPro。输入是一组从0到127的随机生成的整数 这些代码是用Java编写的: 合并排序: 静态无效合并排序(int-arr[]{ int n=阵列长度; if(n

我已经尝试过基准测试,出于某种原因,当在1M元素数组上尝试这两种方法时,
Mergesort
将其排序为0.3s,
Quicksort
将其排序为1.3s


我听说快速排序通常更快,因为它的内存管理,但是如何解释这些结果呢

如果这有什么不同的话,我正在运行MacBookPro。输入是一组从0到127的随机生成的整数

这些代码是用Java编写的:

合并排序:

静态无效合并排序(int-arr[]{
int n=阵列长度;
if(n<2)
返回;
int-mid=n/2;
左整数[]=新整数[mid];
右整数[]=新整数[n-中间];
对于(int i=0;i
您的实现有点简单化:

  • mergesort
    在每次递归调用时分配2个新数组,这很昂贵,但一些JVM在优化此类编码模式方面出人意料地高效
  • quickSort
    对子数组的最后一个元素pivot的选择很差,它为已排序的子数组(包括具有相同元素的子数组)提供了二次时间
数据集是一个伪随机数在小范围
0..127
内的数组,它导致
快速排序
实现的缺点比
合并排序
版本的低效性差得多。增加数据集大小会使这一点更加明显,甚至可能导致堆栈溢出,因为太多的递归调用。具有相同值、增加或减少集合以及此类序列组合等常见模式的数据集将导致
快速排序
实现的灾难性性能

这是一个稍加修改的版本,它较少选择pivot(数组的3/4处的元素),并有一个循环来检测pivot值的重复项,以提高重复值数据集的效率。在我的标准排序基准上,它的性能要好得多(100倍),数组只有40k个元素,但仍然慢得多(8倍)比radixsort:

publicstaticvoidquicksort(int[]arr,int-start,int-end){
int p1=分区(arr、start、end);
int p2=p1;
/*跳过与轴相同的元素*/
而(++p2开始){
快速排序(arr、start、p1-1);
}
如果(p2<结束){
快速排序(arr、p2、end);
}
}
公共静态int分区(int[]arr,int start,int end){
/*选择3/4轴或阵列*/
int i=结束-((结束-开始+1)>>2);
int pivot=arr[i];
arr[i]=arr[end];
arr[end]=枢轴;
for(i=start;i

对于OP的数据集,假设分布具有良好的随机性,扫描重复数据将有助于提高性能。如预期的那样,选择不同的轴心,无论是第一个轴心、最后一个轴心、中间轴心、3/4或2/3轴心,甚至是中位数3轴心,几乎没有影响

对其他非随机分布的进一步测试表明,由于选择了pivot,此
快速排序
实现的性能灾难性。在我的基准测试中,通过选择数组3/4或2/3处的pivot元素,性能得到了极大的提高(对于50k个样本,改进了300倍,比标准合并排序快40%,与
radix_sort
)相比,时间也相当)

  • Mergesort的显著优点是对所有发行版都稳定且可预测,但它需要数据集大小的50%到100%之间的额外内存
  • 仔细实现的快速排序在许多情况下都会更快,并且执行到位,递归只需要日志(N)堆栈空间。但它并不稳定,定制的发行版将表现出灾难性的性能,可能会崩溃
  • Radixsort仅适用于特定类型的数据,如整数和固定长度字符串。它还需要额外的内存
  • Countingsort对于OP的数据集是最有效的,因为它只需要一个128个整数的数组来计算不同值的出现次数,已知范围在0到127之间。对于任何分布,它都将以线性时间执行

Code?Language?Dataset?any?如果您执行效率低下或提供最坏情况的输入,它很容易变慢。这就是我们所能说的,没有更多细节,例如,我们无法帮助您发现测试方法或任何东西中的任何问题。“我听说通常快速排序更快”这句话中的关键词是“一般”.好的,所以这种快速排序速度慢的原因可能是我使用了从0到127的值的输入,这在对1M元素的数组进行排序时会产生大量重复。增加值的间隔可以大大减少使用
public static void quickSort(int[] arr, int start, int end) {
    int partition = partition(arr, start, end);

    if (partition - 1 > start) {
        quickSort(arr, start, partition - 1);
    }
    if (partition + 1 < end) {
        quickSort(arr, partition + 1, end);
    }
}

public static int partition(int[] arr, int start, int end) {
    int pivot = arr[end];

    for (int i = start; i < end; i++) {
        if (arr[i] < pivot) {
            int temp = arr[start];
            arr[start] = arr[i];
            arr[i] = temp;
            start++;
        }
    }

    int temp = arr[start];
    arr[start] = pivot;
    arr[end] = temp;

    return start;
}