目录
一、快排介绍及其思想
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法。
思想:
1.先从数列中取出一个数作为基准数。
2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
3.再对左右区间重复第二步,直到各区间只有一个数。
二、hoare版本
hoare版本是最原始版本,其实现思想如下:
从上面动图我们不难分析出单趟有以下特点:
1. 以首元素为k值
2. 先在右边找比k小的数
3. 然后在左边找比k大的数
4. 最后,k与左边进行交换
我们很容易写出以下代码:
int k = left;
int begin = left;
int end = right;
while (a[k] < a[end])
{
end--;
}
while (a[k] > a[begin])
{
begin++;
}
swap(&a[begin], &a[end]);
我们很容易发现这代码有问题,啥问题?是不是很容易出现越界访问?当没有数比a[end]大时,很容易出现失控,下面也是同理。那么?我们该如何进行处理?很简单,加上控制条件即可,如下:
int k = left;
int begin = left;
int end = right;
while (begin < end && a[k] < a[end])
{
end--;
}
while (begin < end && a[k] > a[begin])
{
begin++;
}
swap(&a[begin], &a[end]);
这样便可进行控制,既然单趟已完成,那么多趟自然不在话下,这里我们用递归方式进行实现。
int PartSort1(int* a, int left,int right)
{
int k = left;
int begin = left;
int end = right;
while (begin < end)
{
while (begin < end && a[k] < a[end]) //这里等号可加可不加
{
end--;
}
while (begin < end && a[k] > a[begin])
{
begin++;
}
swap(&a[begin], &a[end]);
}
swap(&a[begin], &a[k]);
return begin;
}
void QuickSort(int* a, int left,int right)
{
if (left >= right) //递归结束条件判断
{ //当左边与右边相等时,不用进行任何处理
return;
}
int k = PartSort1(a, left, right);
QuickSort(a, left, k - 1);
QuickSort(a, k + 1, right); //区间为:左闭右开
}
那我们这时有个问题:为什么分要从右边开始,为何不能从左边开始?
我们要明白一件事:咱们要确保每一趟的k值的左边一定要比k值小,右边一定要比k值大才行,我们来看下面这组例子:
如果我们从左开始,左边找比k值大的,右边找比k值小的,其结果无外乎为:把6与5换一个位置,仅此而已,咱们的目的肯定会达不到。
要是,我们先找大呢&#