这是我遇到的实现快速排序算法的代码。你能解释一下递归是如何起作用的吗?
void quickSort(int arr[], int left, int right)
{
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
/* partition */
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j--;
if (i <= j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
}
/* recursion */
if (left < j)
quickSort(arr, left, j);
if (i < right)
quickSort(arr, i, right);
}
请注意,这不是作业。
答案 0 :(得分:8)
不确定你的意思是“解释递归是如何工作的”。但是你走了:
您发布的函数采用了一组int和两个索引。它不会对整个数组进行排序,只会对两个索引之间的部分进行排序,忽略它们之外的任何内容。这意味着如果传递第一个和最后一个索引,相同的函数可以对整个数组进行排序,或者如果传递的left
值不是数组的第一个元素的索引和/或right
值不是最后一个元素的索引。
排序算法是众所周知的快速排序。作为枢轴,它使用中心元素(它也可以使用任何其他元素)。它将数组分区为less than (or equal to) pivot
子阵列和greater than (or equal to) pivot
子阵列,留下的元素等于两个分区之间的数据透视。
然后它递归调用自己对两个分区进行排序,但只在必要时才进行排序(因此在递归调用之前是ifs)。
实施有效,但在许多方面都是次优的,可以改进。 以下是一些可能的改进:
答案 1 :(得分:4)
迟到的回复,但我刚刚添加了一些打印件,它可能会帮助遇到这种情况的人理解代码。
#include<iostream>
using namespace std;
void quickSort(int arr[], int left, int right)
{
int i = left, j = right;
int tmp;
int pivot = arr[abs((left + right) / 2)];
cout<<"pivot is"<<pivot<<endl;
/* partition */
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j--;
if (i <= j) {
cout<<"i and j are"<<i<<" "<<j<<"and corresponding array value is"<<arr[i]<<" " <<arr[j]<<endl;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
cout<<"entering first big while loop"<<endl;
for(int i=0;i<7;i++)
cout<<arr[i]<<" "<<endl ;
}
}
cout<<"recursion"<<endl;
/* recursion */
if (left < j)
quickSort(arr, left, j);
if (i< right)
quickSort(arr, i, right);
}
int main(){
int arr[7]= {2,3,8,7,4,9,1};
for(int i=0;i<7;i++)
cout<<arr[i]<<" " ;
quickSort(arr,0,6);
cout<<endl;
for(int i=0;i<7;i++)
cout<<arr[i]<<" " ;
int wait;
cin>>wait;
return 0;
}
答案 2 :(得分:1)
这是你的答案 - 在通常的情况下,将执行递归调用,因为它们之上的条件将为真。但是,在角落情况下,您可以将pivot元素设置为最大(或最小)元素。在这种情况下,您只需要进行一次递归调用,在从数组中删除pivot元素后,通过选择不同的pivot,基本上将再次尝试该进程。