快速排序(quick sort)
1、快速排序:
它采用了
分治的策略
。
分治法(Divide-and-ConquerMethod)的基本思想
:将
原问题分解为若干个规模更小但结构与原问题相似的子问题
。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。
快速排序的基本思想:
①从数列中挑出一个元素(一般是数组中的第一个数或者最后一个数),称为
"基准"(pivot)
;
②重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。结束之后,该基准就处于数列的中间位置。这个过程就称为
分区(partition)操作
;
③
递归
地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归到最底部时,数列的大小是零或一,就结束全部过程(已经排序完成)。
2、快速排序的实现:
图解:
代码实现:
void quick_sort(int s[], int low, int high)
{
if (low < high)
{
int i = low, j =high, key = s[low];
while (i < j)
{
// 从右向左,找第一个小于x的数
while (i < j && s[j] >= key)
j--;
if (i < j)
s[i++] = s[j];
// 从左向右,找第一个大于等于x的数
while (i < j && s[i] < key)
i++;
if (i < j)
s[j--] = s[i];
}
//把基准数放在相应位置上
s[i] = key;
// 递归调用
quick_sort(s, low, i - 1);
quick_sort(s, i + 1, high);
}
}
语言描述:
①设置两个变量i、j,初次排序开始的时候:i=0,j=N-1;
②以第一个数组元素作为基准数,赋值给key,即key=s[0];
③从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值s[j],将A[j]和A[i]互换;没找到符合条件的值,使得j=j-1;
④从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的s[i],将A[i]和A[j]互换;没找到符合条件的值,使得i=i+1;
⑤重复第3、4步,直到i=j。
3、快排的时间复杂度和空间复杂度
①最好情况:
时间复杂度为:O(nlogn)
,即每次划分产生的两个区间大小都为区间总长(设为n)的一半;
空闲复杂度为:O(logn)
;
②最坏情况:
时间复杂度为:O(n^2)
,即每次划分产生的两个区间大小分别包含n-1个元素和1个元素;
空闲复杂度为:O(n)
;
注:快排使用的空间为:O(1),真正消耗空间的是递归调用。