算法思想
采用分治的思想,步骤可以概括为:
- 选取基准值pivot(一般默认选开始的位置)
- 将小于pivot的数放在左边,大于pivot的数放在右边(挖坑填补法)
- 对pivot左边和右边的序列分别递归执行步骤1、2
代码实现
1 | public class Quicksort { |
- 初始main第4行调用quicksort(array, 0, 9);
- left为0,right为9,pivot为5
- left为0,right为9,left小于right,进入15行if结构体
- left为0,right为9,left小于right,进入16行while结构体
- 17行的while条件中array[right] = array[9] = 3,小于pivot为5,退出while循环
- 20行array[left] = array[right],即array[0] = array[9],此时array变成[3,2,4,1,6,8,10,7,9,3];
- 22行的while循环一直到left = 4才停止,此时array[left] = array[4] = 6,大于pivot为5,退出while循环
- 25行array[right] = array[left], 即array[9] = array[4],此时array变成[3,2,4,1,6,8,10,7,9,6];
- 此时left为4,right为9,left小于right,再次进入16行while结构体
- 17行的while循环一直到left = right,都为4,此时不满足right > left,退出while循环
- 20行array[left] = array[right],即array[4] = array[4],此时array还是[3,2,4,1,6,8,10,7,9,6];
- 22行的while循环不满足left < right,退出while循环
- 25行array[right] = array[left],即array[4] = array[4],此时array还是[3,2,4,1,6,8,10,7,9,6];
- 此时left = right = 4,不满足循环条件,退出16行的while
- 28行array[right] = pivot,即array[4] = 5,此时array变成[3,2,4,1,5,8,10,7,9,6],此时小于5的值都在5的左边,大于5的值都在5的右边
- 30行调用quicksort(array,0,5);
- 31行调用quicksort(array,7,9);
- left为0,right为9,left小于right,进入16行while结构体
复杂度
时间复杂度
- 最好情况O(nlogn):当每次选择的基准值都是待排序列的中值时,总共需要递归O(logn)次,每层花费时间O(n),即O(nlogn);
- 最差情况O(n2):当每次选择的基准值都是待排序列的最值时,相当于直接插入排序,总共需要递归O(n)次,每层花费时间O(n),即O(n2);
- 平均情况O(nlogn)
空间复杂度
概括来讲快排的每层都只使用了常数空间(一个空间用于保存pivot的值),因此空间复杂度等于递归调用的深度即最好为O(logn),最差为O(n);
稳定性
- 不稳定:待排序列为[6,1,3,7,3](注意原来不加粗3在加粗3的左边),经过一次排序后(以6为pivot),序列变成[3,1,3,6,7],最终排序结果为[1,3,3,6,7],可以发现不加粗3到了加粗3的右边,相等元素之间相对位置发生了变化,因此快排是不稳定的
总结
排序方式 | 时间复杂度 | 空间复杂度 | 稳定性 |
---|---|---|---|
快速排序 | 最好为O(nlogn),最差为O(n2),平均为O(nlogn) | 最好为O(logn),最差为O(n) | 不稳定 |