void QuickSort(int* a, int left, int right)
{
if (left >= right)//如果区间只剩一个数或没有数就不进行操作
return;
int key = PartSort(a, left, right);//调用单趟排序函数,取key的位置
QuickSort(a, left, key - 1);//递归调用,对左区间进行排序
QuickSort(a, key + 1, right);//递归调用,对右区间进行排序
}
上面是简单模型
hoare方法
这个方法取自于快排的发明者本人
其单趟排序的思路是:取区间中最左或最右边的元素为key,定义两个变量,这里假设是p和q,q从区间的最右边向左走,找到比key小的元素就停下。p从最左边向右走,找到比key大的元素就停下。然后交换p和q所指向的元素。下面是p与q单次交换的示意图:
重复上面的过程,直到pq相遇,交换key和pq相遇位置的元素。
这样,单趟排序就完成了。
可以看出,经过pq的不断交换,比key小的值换到了左边,比key大的值换到了右边。最终将key换至中间就完成了单趟排序。
这里的key可以取最左边的值,此时必须让最右边的q先走。因为在最后一个循环时,若是q向左走,撞上了p,p此时指向的元素是上一个循环结束后交换的值,这个值比key小。若是p向右走,撞上了q,那么在这个循环,q先走,并且q停下来了,所以q的位置是一个比key小的值。若让左边的p先走,则可能在最后交换key的步骤将一个大于key的值交换到最左边。具体原因不进行分析。
若要取最右边的值做key,则要让最左边的p先走,原因同上。
下面是代码实现:
int PartSort1(int* a, int left, int right)
{
int key = left;//取最左边的元素做key
while (left < right)//当左右没有相遇
{
while (left < right && a[right] >= a[key])//如果右比key小就退出循环
right--;
while (left < right && a[left] <= a[key])//如果左比key大就退出循环
left++;
swap(&a[left], &a[right]);//交换左右
}
swap(&a[key], &a[left]);//交换key和相遇位置的元素
return left;//返回key的位置
}