算法原理
- 如果要排序下标为p到r之间的一组数组;
- 选择p到r之间任意一个元素做pivot(分区点),将小于pivot的元素放在左边,大于pivot的放在右边,pivot放在中间。这样数组就被分为三个部分,小于pivot的区间A[p, q-1]、等于pivot的区间A[q]、大于pivot的区间A[q+1, r];
- 根据分治思想和递归编程技巧,我们可以用递归排序区间A[p, q-1]和区间A[q+1, r],直到区间缩小为1,就说明数组有序了;
如何实现
- 递推公式:quick_sort(p, r) = quick_sort(p, q-1) + quick_sort(q+1, r);
- 终止条件:p >= r;
算法稳定性
因为区分过程中涉及交换操作,如果数组中有两个8,一个是pivot,经过分区处理后,后面的8可能放到前面去了。比如数组[]1,2 , 3, 9, 8, 11, 8],取后面的8做pivot,那么分区后就会将后面的8与9进行交换。因此,快速排序不是稳定排序算法。
时间复杂度
快速排序也是用递归实现的,因此时间复杂度也可以用递归公式表示。
- 最好情况:每次分区都可以将数组分为大小差不多相等的两部分,这时候时间复杂度为O(nlog);
- 最差情况:如果某个数组是已经排序好的,那么每次得到的两个区间都极端不等,那么就需要n次分区,每次需要平均扫描n/2个元素,这种情况下快排的时间复杂度就是O(n^2);比如([0, 1, 2 , 3, 4, 5, 6, 7, 8, 9])
- 平均情况:快速排序算法大部分情况下时间复杂度为O(nlogn),只有在极端情况下才会退化到O(n^2),我们也有很多可以降低这个概率;
空间复杂度
快排是一种原地排序算法,因此空间复杂度为O(1)。
《数据结构与算法之美》 -- 王争