public class QuickSort {
public static void quickSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
quickSort(arr, 0, arr.length - 1);
}
private static void quickSort(int[] arr, int left, int right) {
if (left < right) {
// 基准值的位置。
int partitionIndex = partition(arr, left, right);
quickSort(arr, left, partitionIndex - 1);
quickSort(arr, partitionIndex + 1, right);
}
}
private static int partition(int[] arr, int left, int right) {
// 选定一个基准值,基准值可以随机取任何一个值,我们这里选择最左边的元素作为基准值,直接用left表示就可以
// index永远指向基准值位置的下一个位置,或者说,index左边的 都是比基准值小的元素
int index = left + 1;
// 开始遍历序列,基准值选择了序列最左边的元素,所以从第二个开始往后,挨个和基准值比较
for (int i = index; i <= right; i++) {
// i是从前往后的一个快指针
if (arr[i] < arr[left]) {
// 如果比基准值小,说明它应该在基准值的左边,交换i和index位置的元素位置,保证index左边都是比它小的元素
swap(arr, i, index);
index++;
}
}
// 最后,把index左边的元素和基准值交换,因为index左边的元素本来就是比基准值小的,所以换完对排序没影响
swap(arr, left, index - 1);
// 最后基准值的位置就是index-1,下一次迭代,就是迭代基准值左边和右边的。
return index - 1;
}
private static void swap (int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
4、复杂度分析
对于快排而言,基准的选择,对排序效率有很大的影响,如果根据基准值,每次划分的两个子序列其中一个总是只包含一个元素(如示例中产生过的情况),那么快排的时间复杂度为O(
n
2
n^2
n2),如果根据基准值,每次划分的两个子序列包含的元素数量是一致的,那么快排的时间复杂度为O(
n
l
o
g
n
nlogn
nlogn)。但是,最坏的情况发生的概率是很低的,因为在每一次划分的时候,都让一边只包含一个元素的情况是几乎不可能发生的,所以快排的平均时间复杂度是O(
n
l
o
g
n
nlogn
nlogn)。