Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.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++_Sorting_Quicksort - Fatal编程技术网

C++ 当数组中有等效元素时,为什么我的简单快速排序实现会失败?

C++ 当数组中有等效元素时,为什么我的简单快速排序实现会失败?,c++,sorting,quicksort,C++,Sorting,Quicksort,我正在做一些练习题来更新我的旧算法课程,我正在尝试实现快速排序。是的,我知道在生产代码中我们应该使用std::sort,但这是出于教育目的:) 我有下面的代码。当数组中的所有元素都是唯一的,但当存在重复的元素时,它不起作用。怎么会?我在哪里犹豫过 void quicksort(int arr[], int left, int right) { // base case: if (left >= right) return; // alternati

我正在做一些练习题来更新我的旧算法课程,我正在尝试实现快速排序。是的,我知道在生产代码中我们应该使用
std::sort
,但这是出于教育目的:)

我有下面的代码。当数组中的所有元素都是唯一的,但当存在重复的元素时,它不起作用。怎么会?我在哪里犹豫过

void quicksort(int arr[], int left, int right)
{
    // base case:
    if (left >= right)
        return;

    // alternative case:
    int pivot_index = (left + right)/2;
    int pivot = arr[pivot_index];

    int i = left, j = right;
    int tmp;

    while (i < j)
    {
        // scan from left until elem > pivot or left == right, 
        while (arr[i] < pivot)
            ++i;

        // scan from right until elem < pivot or right == left.
        while (arr[j] > pivot)
            --j;

        if (i < j)
        {
            tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
            ++i;
            --j;
        }
    }
    // recurse on left and right.
    if (i > left)
        quicksort(arr, left, i);
    if (i < right)
        quicksort(arr, i + 1, right);
}

void main()
{
    const int arr_size = 7;
    int arr[arr_size] = {1,2,4,3,9,5,2};
    quicksort(arr, 0, arr_size - 1);

    for (int i = 0; i < arr_size; ++i)
    {
        std::cout << arr[i] << ", ";
    }
}
void快速排序(int-arr[],int-left,int-right)
{
//基本情况:
如果(左>=右)
返回;
//备选案例:
int pivot_index=(左+右)/2;
int pivot=arr[pivot_index];
int i=左,j=右;
int tmp;
而(i轴或左==右,
while(arr[i]pivot)
--j;
if(i左)
快速排序(arr,左,i);
如果(我<对)
快速排序(arr,i+1,右);
}
void main()
{
const int arr_size=7;
int arr[arr_size]={1,2,4,3,9,5,2};
快速排序(arr,0,arr_大小-1);
对于(int i=0;istd::cout如果left==right,则没有回退。如果没有捕获,则代码将不会执行任何操作

if (i > left)
    quicksort(arr, left, i);
if (i < right)
    quicksort(arr, i + 1, right);
轴是索引2处的4,在第一次扫描
i==0
j==2
之后,两个4被交换,
i
增加,
j
减少,因此现在
i==j==1
,循环停止

然后递归调用排序
{4,8}
resp
{4,5,6}
,结果排序不正确

您可以通过将至少一个扫描条件替换为
arr[i]=pivot
来避免该问题,但是您需要防止从阵列中跑掉(当pivot是最大或最小的元素时),最好将条件
i
包含在其中

如果在交换时分别减小索引

if (i < j)
{
    tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
    ++i;
    --j;
}
导致
i==j
指向
y
,并且您没有关于
y
与轴比较的信息

因此,您需要检查
y
并处理不同的可能性

但是如果没有重复的元素,您的实现也是不正确的;请考虑

{ 1, 4, 5, 6, 9, 3, 2 }
           ^
         pivot
首先,
i
递增,直到它指向枢轴,
j
保持指向2。这两个值互换,
i
递增,
j
递减,因此现在情况变得更糟

{ 1, 4, 5, 2, 9, 3, 6 }
              ^  ^
              i  j
arr[i]>pivot
arr[j]
,因此交换、递增
i
、递减
j

{ 1, 4, 5, 2, 3, 9, 6 }
              ^  ^
              j  i

现在
j
,循环停止,但是递归调用是
快速排序(arr,0,5);
快速排序(arr,6,6);
,因此“排序”中的最后一个元素数组不是数组中最大的元素。

如果运行此程序,则不会发生这种情况。它实际上是无限递归的。这是快速排序方法的第一部分,即基本case.stack溢出,来自快速排序递归调用!非常有趣。因此,问题在于If中的递增/递减配对(i[左,枢轴位置-1]
[枢轴位置+1,右]
。不知道如何在不先将枢轴换到一边的情况下修复它。
{ 1, 4, 5, 2, 9, 3, 6 }
              ^  ^
              i  j
{ 1, 4, 5, 2, 3, 9, 6 }
              ^  ^
              j  i