Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当数组具有重复值时,为什么快速排序算法的持续时间会增加?_C++_Performance_Time Complexity_Quicksort_Mergesort - Fatal编程技术网

C++ 当数组具有重复值时,为什么快速排序算法的持续时间会增加?

C++ 当数组具有重复值时,为什么快速排序算法的持续时间会增加?,c++,performance,time-complexity,quicksort,mergesort,C++,Performance,Time Complexity,Quicksort,Mergesort,我试图使用std::chrono time计算并使用某个范围内随机生成的整数数组[A,B]来测量合并排序和快速排序函数的持续时间,数组的大小从5000到100000个整数不等 我的代码的目标是证明,当快速排序中选择(枢轴)的方法得到改进时,快速排序函数最终处理数组的时间比合并排序少,我选择枢轴的方法是使用随机索引方法来最小化复杂性为(n^2)的概率,然而,在我将在下面描述的某些情况下,快速排序最终比合并排序花费更多的时间,我想知道为什么会发生这种情况 案例1: 数组中的数字范围很小,这增加了数组

我试图使用std::chrono time计算并使用某个范围内随机生成的整数数组[A,B]来测量合并排序和快速排序函数的持续时间,数组的大小从5000到100000个整数不等

我的代码的目标是证明,当快速排序中选择(枢轴)的方法得到改进时,快速排序函数最终处理数组的时间比合并排序少,我选择枢轴的方法是使用随机索引方法来最小化复杂性为(n^2)的概率,然而,在我将在下面描述的某些情况下,快速排序最终比合并排序花费更多的时间,我想知道为什么会发生这种情况

案例1: 数组中的数字范围很小,这增加了数组中存在重复数字的概率

案例2: 当我使用像clion这样的本地IDE时,快速排序函数比合并排序花费的时间要多得多,但是像IDEONE.com这样的在线编译器在两种排序算法中给出了相似的结果(即使生成的整数范围很小)

以下是我在上述情况下得到的结果(第一行数字是合并排序结果,第二行是快速排序结果):

1-clion结果数字范围窄(-100600)

具有广泛数字范围的2-clion结果(INT_MIN,INT_MAX)

数字范围很窄的3-IDEONE结果(-100600)

4-数字范围广泛的表意文字结果(INT_MIN,INT_MAX)

#包括
#包括
#包括
使用名称空间std;
mt19937 gen(时钟::稳定时钟::现在().自新纪元以来的时间().计数());
int*generatarray(int大小)
{
int*arr=新的int[size];
均匀分布(最小值、最大值);
对于(int i=0;i对于(int i=0;i已知,当输入集包含大量重复项时,快速排序的性能较差。解决方案是使用三向分区,如上所述:

重复元素

使用如上所述的分区算法(甚至 如果选择了好的轴心点值,快速排序将表现出较差的性能 包含许多重复元素的输入的性能 当所有的输入元素都相等时,问题很明显:at 每次递归,左分区都是空的(没有输入值小于 右分区只减少了一个 元素(轴心被移除)。因此,算法需要 对相等值数组进行排序的二次时间

为了解决这个问题(有时称为),可以使用替代的线性时间划分例程 将值分为三组:小于 轴,值等于轴,值大于轴。 …价值观 等于轴的已排序,因此只有小于和 大于的分区需要递归排序。在伪代码中, 快速排序算法变为

algorithm quicksort(A, lo, hi) is
    if lo < hi then
        p := pivot(A, lo, hi)
        left, right := partition(A, p, lo, hi)  // note: multiple return values
        quicksort(A, lo, left - 1)
        quicksort(A, right + 1, hi)
输出:

0 1 2 3 4 5 6 7 8 9 11 11 12 13 14 15 16 19 18 19
0 0 0 1 0 1 1 1 1 1 2 3 2 2 2 2 3 3 3 3

0 1 2 3 4 5 6 6 8 8 9 12 11 12 13 14 16 17 18 19
0 0 1 1 1 2 3 3 3 4 4 4 5 6 5 6 7 7 8 8
因此,使用大量重复项的运行现在要快得多

当数组具有重复值时,为什么快速排序算法的持续时间会增加

这只有在使用Lomuto类型的分区方案时才是正确的,其中重复的值会导致拆分变得更糟


如果使用霍尔分区方案,当数组具有重复值时,算法持续时间通常会缩短,因为拆分更接近于完全对半拆分的理想情况,并且改进的拆分可以补偿具有内存缓存的典型系统上的额外交换。

如果在代码中交换顺序,会发生什么d首先测量合并排序,然后快速排序?用于编译的编译器选项是什么?编译器是mingw64,交换顺序会得到相同的结果。什么编译器选项?优化已打开?您能详细说明吗?我不知道如何共享我的编译器选项,但我确信我没有更改任何clion编译器选项。是吗这是调试版还是发布版?请注意,wiki文章后来被更正为只针对Lomuto分区方案存在此问题。对于Hoare分区方案,随着重复值数量的增加,拆分更接近理想情况,即完全对半拆分,足以补偿在典型系统上进行的更多交换使用缓存。
pair<int,int> partition(int* arr, int left, int right)
{
    int idx = left + (right - left) / 2;
    int pivot = arr[idx]; // to be improved to median-of-three
    int i = left, j = left, b = right - 1;
    while (j <= b) {
        auto x = arr[j];
        if (x < pivot) {
            swap(arr[i], arr[j]);
            i++;
            j++;
        } else if (x > pivot) {
            swap(arr[j], arr[b]);
            b--;
        } else {
            j++;
        }
    }
    return { i, j };
}
void quickSort(int* arr, int left, int right)
{
    if (left < right)
    {
        pair<int, int> part = partition(arr, left, right);
        quickSort(arr, left, part.first);
        quickSort(arr, part.second, right);
    }
}
0 1 2 3 4 5 6 7 8 9 11 11 12 13 14 15 16 19 18 19
0 0 0 1 0 1 1 1 1 1 2 3 2 2 2 2 3 3 3 3

0 1 2 3 4 5 6 6 8 8 9 12 11 12 13 14 16 17 18 19
0 0 1 1 1 2 3 3 3 4 4 4 5 6 5 6 7 7 8 8