首先确定要排序的数组索引范围 p-r;任选p-r一个节点作为分割值 pivot,此处选择r作为pivot
通过两个索引一个待替换索引i,和一个循环比较索引j来实现,将小于pivot的值放到pivot左边,当arr[j]>=pivot不替换,j++,i不变,直到遇到arr[j]<pivot;此时arr[i]和arr[j]互换,同时 j++,i++
最后当j走到了pivot的上一个节点,此时arr[i]就是pivot的最终排序位置
如此递归,直至p和r重合,即可将数组整体排序
注意:冒泡排序和插入排序等如果遇到值相同的值不会改变原来的顺序,快排排序不能保证原来的顺序,如上图中两个6的顺序会反过来
public class FastSorted {
public int partition(int[] arr,int p, int r){
//p头 索引 r尾部索引
int pivot = arr[r];
int i = p;
for(int j=p;j<r;++j){
if(arr[j] < pivot){
//swap
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
}
}
int temp = arr[i];
arr[i] = pivot;
arr[r] = temp;
return i;
}
public void fastSorted(int[] arr, int p, int r){
if(p >= r){
return;
}
int q = partition(arr, p, r);
fastSorted(arr, p, q-1);
fastSorted(arr, q+1, r);
}
public static void main(String[] args) {
int[] arr = new int[]{6,8,7,6,3,5,2,4};
FastSorted fastSorted = new FastSorted();
fastSorted.fastSorted(arr, 0, arr.length-1);
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
}
}
- 空间复杂度:由于整个递归只涉及到几个局部临时变量定义,所以空间复杂度为O(1);
- 时间复杂度:
- 最好的情况已经数组本身排好序:每一项都会触发swap;i++;j++ 他们的值一致,执行fastSorted后q=r,跳出递归,时间复杂度o(n)
- 最差情况:顺序相反,每次都只执行pivot和arr[p]的swap,但是每次都需要比较n次,总共有n条数据,所以会执行n-1次 pivot和arr[p]的swap,n(n-1) 时间复杂度o(n^2)
- 平均情况:每一次递归得出最终pivot的排序位置,都位于数组正中间索引,总共递归log2 n次,每次总共比较n次,时间复杂度nlog2 n