采用交换法的实现:
// 递归实现
public void digui(int[] a, int left, int right) {
if (left >= right) return;
int pivot = left;
int l = left + 1;
int r = right;
// 注意三个地方为 l <= r(而不是 l < r),否则可能会引起错误的元素交换
while (l <= r) {
// l <= r 则可以保证不会数组越界
while (l <= r && a[l] <= a[pivot]) {
++l;
}
// l <= r 则可以保证不会数组越界
while (l <= r && a[r] >= a[pivot]) {
--r;
}
// 如果 l == r 则没必要交换
if (l < r) {
Common.sweap(a, l, r);
}
}
Common.sweap(a, left, r);
digui(a, left, r - 1);
digui(a, r + 1, right);
}
// 迭代实现
public void diedai(int[] a) {
// 大致跟递归的实现相同,只不过需要一个容器用于存放中间过程中子数组的边界 index
Queue<int[]> list = new LinkedList<>();
int[] first = new int[]{0, a.length - 1};
list.add(first);
// 然后需要主要的就是在利用容器进行循环操作时
// 要避免 java.util.ConcurrentModificationException
while (!list.isEmpty()) {
int[] tmp = list.poll();
int p = tmp[0];
int l = p + 1;
int r = tmp[1];
while (l <= r) {
while (l <= r && a[l] <= a[p]) ++l;
while (l <= r && a[r] >= a[p]) --r;
if (l < r) {
Common.sweap(a, l, r);
}
}
Common.sweap(a, p, r);
if (p < r - 1) {
list.add(new int[]{p, r - 1});
}
if (r + 1 < tmp[1]) {
list.add(new int[]{r + 1, tmp[1]});
}
}
}
针对于上面的交换法的递归实现进行性能分析:
最好的情况为每次划分过程产生的区间大小都为 n/2
,则时间复杂度为 O(n log n),其中 n 代表内部循环的时间复杂度(即上面外层的 while 循环,这个是固定的),而对于空间复杂度,递归树的深度为 log2 n,其空间复杂度也就为 O(log n);
最坏的情况则是每次划分过程产生的两个区间分别包含 n-1 个元素和 1 个元素的时候,则时间复杂度为 O(n2),而对于空间复杂度,需要进行n‐1递归调用,其空间复杂度为 O(n);
平均情况:时间复杂度为 O(n log n),空间复杂度为 O(log n)。
具体参考:https://baike.baidu.com/item/快速排序算法/369842?fromtitle=快速排序&fromid=2084344#6_3
对于迭代的实现,本质上也是一样的。
快速排序是一种不稳定的排序。