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;i std::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