想法:
乱序数组中找任一个元素,做 pivot。
比 pivot小的,放到pivot左侧,反之放右侧。
以 pivot 为中心,对其左右两个子数组,递归执行前两步,直到最后子数组长度为1结束。
细节:
怎么完成第二步的?
具体方法是,数组两端各有一个指针low,high,都往中间扫,各自指向不符合的元素(low指向大于pivot的元素,high指向小于等于pivot的元素),此时若low<high,则将两元素对换,否则让 high/low 指向的元素与 pivot 所在元素互换位置,完成。(扫描结束时low与high相邻low在high右侧, high指向的元素是<=pivot的,low指向元素是大于pivot的。假设此时pivot在low的左侧,如果low指向的元素与pivot对调,pivot左侧就不是全小于等于pivot,所以pivot与high相换,如果此时pivot在low的右侧,那么同理,应该与low对调)
也就是先把除了 pivot 以外的数组分为两边,一边所有元素小于另一边的所有元素。最后把 pivot ,放到中间。
可以看到第二步就是把数组遍历了一次,另外,还可以看到此番“交换”,只用了三个指针的额外空间。
时间复杂度:
递归结束的条件是所有子数组长度为1。比如长度为 10,如果 7 个元素大于 pivot,2 个元素小于 pivot,那么拖后腿的部分就可能是 7 。所以最理想情况是,每轮都对半。每一轮都会去掉1个pivot元素,列下公式如下。
n + (n/2+n/2 - 1) + (n/4+n/4+n/4+n/4 - 2) + ....+ (1+1+..+1 - log2n) = O(log2n 个 n 的相加) = O(nlog2n)
1 2 3 最后一轮
所以最好的时间复杂度就是 O(nlog2n)。
最坏的情况每一轮,都是 0:n-1的局面。
n + n-1 + n-2 + .... + 1 = O(n2)
平均情况是一个把所有情况的复杂度相加除以情况数算出来的,比较复杂,这里直接上结论就是最好情况的 O(nlog2n)
空间复杂度:
前面已经分析过每一轮都是3个指针,所以最好情况一共log2n轮, 3*log2n = O(log2n),平均情况下也是
稳定的排序算法:
假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
在快排中稳不稳这就要看运气了,比如 3,5(1),5(2),2,6 ,
如果以3为 pivot,第一轮排序后,2,3,5(2),5(1),6
如果以5(2) 为 pivot,第二轮排序后,2,3,5(2),5(1),6
如果以 5(1) 为 pivot,第三轮排序后 ,2,3,5(2),5(1),6
看运气的稳就是不稳。
上代码:
代码方便起见,将pivot指向数组首个元素,这样每次扫描结束后high与pivot对换。
public class QuickSort {
public static void main(String[] args) {
int[] elements = new int[]{1,3,4,2,7,6,5};
qsort(elements, 0, elements.length-1);
for (int element : elements) {
System.out.print(element + " ");
}
}
private static void qsort(int[] elements, int start, int end){
if(end <= start){
return;
}
int pivot = start;
int low = start;
int high = end;
while(low<high){
while(low < end && elements[low]<=elements[pivot]) {
low++;
}
while(high > start && elements[high]>elements[pivot]){
high --;
}
if(low<high) {
int tmp = elements[low];
elements[low] = elements[high];
elements[high] = tmp;
}
}
int tmp = elements[high];
elements[high] = elements[pivot];
elements[pivot] = tmp;
qsort(elements, start, high-1);
qsort(elements, high+1, end);
}
}