快排利用的也是分治思想。乍看起来,它有点像归并排序,但是思路其实完全不一样
快排的思想是这样的:如果要排序数组中下标从 p 到 r 之间的一组数据,我们选择 p 到 r
之间的任意一个数据作为 pivot(分区点)。
我们遍历 p 到 r 之间的数据,将小于 pivot 的放到左边,将大于 pivot 的放到右边,将
pivot 放到中间。经过这一步骤之后,数组 p 到 r 之间的数据就被分成了三个部分,前面 p
到 q-1 之间都是小于 pivot 的,中间是 pivot,后面的 q+1 到 r 之间是大于 pivot 的。
伪代码如下:
//按照设定的 pivot,将下标 r 到 q 的元素分为两部分,一部分小于 pivot,另外一部分大于 pivot,并返回 新的分割点
int partition(data,r,q){
}
void quick_sort(data,r,q){
if(r>=q)
return
int p = partition(data,r,q)
quick_sort(data,r,p-1)
quick_sort(data,p+1,q)
}
void test(){
quick_sort(0,data.length-1)
}
java 代码:
public class SortTest {
private void swap(int[] data,int i,int j){
int tmp = data[i];
data[i] = data[j];
data[j] = tmp;
}
public void printArray(int[] data){
for(int d:data){
System.out.print(d+" ");
}
System.out.println();
}
/**
* 快速排序
*/
public int partition(int[] data,int r,int q){
int pivot = q;
int start = r;
for(int j=r;j<q;j++){
if(data[j]<data[pivot]){
swap(data,start++,j);
}
}
swap(data,start,pivot);
return start;
}
public void quick_sort(int[] data,int r,int q){
if(r>=q){
return;
}
int pivot = partition(data,r,q);
quick_sort(data,r,pivot-1);
quick_sort(data,pivot+1,q);
}
@Test
public void test5(){
int[] data = {55,76,34,66,22,31,13,25,90,87,56,65,66};
//int[] data = {6,7,8,9,1,2,3,4,5};
//partition(data,0,data.length-1);
quick_sort(data,0,data.length-1);
printArray(data);
}
}
结果:
13 22 25 31 34 55 56 65 66 66 76 87 90
分析:快速排序算法只在交换时,耗费了常数的空间复杂度,因而是原地排序算法;
其在 partition 函数中,交换时,会影响值相同元素的先后顺序,因而是不稳定的算法;
快速排序的在大部分情况下的时间复杂度都可以做到 O(nlogn),只有在极端情况下,才会退化到 O(n2),且概率极低