基本思想
快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
代码实现
第一种方法:左右指针法
1.begin从最左边开始,end从最右边开始,用三数取中法设置key
2.begin向右找大于key的数据,end向右找小于key的数据,找到之后进行交换
3.相遇之后,因为begin先走,所以相遇点一定比key大,key跟相遇点交换。
int GetMid(int* array, int left, int right) //三数取中法
{
int mid = left + ((right - left) >> 1);
if (array[left] < array[mid])//左比中小
{
if (array[mid] < array[right])
return mid;//mid是中位数
else if (array[left] > array[right])
return right;
else
return left;
}
else
{
if (array[mid] > array[right])
return mid;
else if (array[left] > array[right])
return right;
else
return left;
}
}
int PartSort1(int* array, int left, int right) //左右指针法
{
assert(array);
int begin = left;
int end = right;
int mid = GetMid(array, left, right);
Swap(&array[mid], &array[right]);
int key = array[right];
while (begin < end)
{
while (array[begin] <= key && begin < end)//begin找大
{
begin++;
}
while (array[end] >= key && begin < end)//end找小
{
end--;
}
if (begin < end)
{
Swap(&array[begin], &array[end]);
} //begin end 相遇后,把key放在相遇位置上
}
Swap(&array[begin], &array[right]);//begin end 相遇后,把key放在相遇位置上
return begin;
}
第二种方法:挖坑法
1.三数取中法选取适中大小的数作为key,跟最右边数据进行交换。
2.key作为坑,最左数据为begin,最右数据为end,begin找大,end找小。
3.begin,end,找到数据之后跟坑key交换,相遇之后停止。
这种方法原理上类似于左右指针法,参考上面的图解。
int PartSort2(int* array, int left, int right) //挖坑法
{
assert(array);
int begin = left;
int end = right;
int key = array[right];
while (begin < end)
{
while (array[begin] <= key && begin < end)
{
begin++;
}
array[end] = array[begin]; //坑变为begin
while (array[end] >= key && begin < end)
{
end--;
}
array[begin] = array[end]; // 坑变为end
}
array[begin] = key; //填坑
return begin;
}
第三种方法:前后指针法
1.定义变量cur指向序列的开头,定义变量pre指向cur的前一个位置。
2.当array[cur] < key时,cur和pre同时往后走,如果array[cur]>key,cur往后走,pre留在大于key的数值前一个位置。
3.当array[cur]再次 < key时,交换array[cur]和array[pre]。
在没找到大于key值前,prev永远紧跟cur,遇到大的两者之间机会拉开差距,中间差的肯定是连续的大于key的值,当再次遇到小于key的值时,交换两个下标对应的值就好了。
int PartSort3(int* array, int left, int right) //前后指针
{
assert(array);
int prev = left - 1;
int cur = left;
int key = array[right];
while (cur < right)
{
if (array[cur] < key && ++prev != cur)
{
Swap(&array[cur], &array[prev]);
}
++cur;
}
Swap(&array[++prev], &array[right]);
return prev;
}
以下为测试代码:
void QuickSort(int* array, int left, int right) //快速排序
{
assert(array);
if (left >= right)
return;
//int div = PartSort1(array, left, right);
//int div = PartSort2(array, left, right);
int div = PartSort3(array, left, right);
printf("div:%d\n", div);
//left div-1
QuickSort(array, left, div - 1);
//div+1 right
QuickSort(array, div + 1, right);
}
时间复杂度及稳定性
平均时间复杂度: O(nlogn)
最坏时间复杂度:O(n2) (有序的情况)
稳定性:不稳定