快速排序
基本思想
取待排序元素中的某一个元素作为基准值,按照该基准值将待排序集合分为两部分,左子序列中的元素均小于基准值,右子序列中的所有元素均大于基准值,然后左右子序列重复该过程,直到所有元素都已排好序。
快速排序整体上使用的是一个分治的思想,在实现方面需要将大问题化为一个个小问题,直到部分小区间全部有序或者小区间内没有数。在处理区间的问题上,我们使用的是前闭后闭的方式。
基于此我们可以写出如下代码
void __Quicksort(int *array, int left, int right)
{
if(left == right){ //只有一个数已经有序
return;
}
if(left > right){ //没有数不需要排序
return;
}
int div = Partition(array, left, right);
__Quicksort(array, left, div-1);
__Quicksort(array, div+1, right);
}
void Quicksort(int *array, int size)
{
__Quicksort(array, 0, size-1);
}
有三种方法来处理一个序列使小元素位于基准值的左边,大元素位于基准值的右边:
hoare法
挖坑法
前后指针法
hoare法
static void Swap(int *x, int *y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
int Partition(int *array, int left, int right)
{
int begin = left;
int end = right;
while(begin < end){
while(begin < end && array[begin] <= array[right]){
begin++;
}
while(begin < end && array[end] >= array[right]){
end--;
}
Swap(array+begin, array+end);
}
Swap(array+begin, array+right);
return begin;
}
挖坑法
int Partition(int *array, int left, int right)
{
int begin = left;
int end = right;
int key = array[right];
while(begin < end){
while(begin < end && array[begin] <= key){
begin++;
}
array[end] = array[begin];
while(begin < end && array[end] >= key){
end--;
}
array[begin] = array[end];
}
array[begin] = key;
return begin;
}
前后指针
定义两个变量div和cur都先指向第一个元素,使div始终指向比基准值小的最后一个元素,cur向后遍历,遇到比基准值小的便交换div和cur,直到cur走到基准值的前一个元素,交换array[div]和array[right]。
int Partition(int *array, int left, int right)
{
int div = 0, cur = 0;
for(div = left, cur = left; cur < right; cur++){
if(array[cur] < array[right]){
Swap(array+div, array+cur);
div++;
}
}
Swap(array+div, array+right);
return div;
}