快速排序(Quicksort),又称划分交换排序(partition-exchange sort),简称快排,是一种效率很高的排序算法。快速排序是不稳定的排序方法,当数组是完全无序时, 时间复杂度最低,为O(nlog2n) ,当数组完全有序时,时间复杂度最高,为O(n^2)。
排序思路:
·从数列中挑出一个元素,称为"基准"。
·重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任何一边)。
在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。
·递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。
·递归到最底部时,数列的大小是零或一,也就是已经排序好了。这个算法一定会结束,因为在每次的迭代(iteration)中,
它至少会把一个元素摆到它最后的位置去。
看以下程序:
import java.util.Arrays;
public class QuickSort {
/** 找基准 */
public static int partion(int[] arr, int start, int end) {
int tmp = arr[start];
while (start < end) {
// 若结束索引对应数据大于开始索引对应数据,结束索引前移
while (arr[end] >= tmp && start < end) {
--end;
}
// 若开始索引和结束索引相遇,说明该数据已经有序
if (start >= end) {
break;
}else {
// 若结束索引对应的数据小于开始索引对应的值,将结束索引对应的数据赋值给开始索引
arr[start] = arr[end];
}
// 若开始索引对应数据结束索引对应数据,开始索引后移
while (arr[start] <= tmp && start < end) {
++start;
}
// 若开始索引和结束索引相遇,说明该数据已经有序
if (start >= end) {
break;
}else {
// 若开始索引对应的数据大于结束索引对应的值,将开始索引对应的数据赋值给结束索引
arr[end] = arr[start];
}
}
arr[start] = tmp;
// 返回基准对应的索引
return start;
}
public static void quickTest(int[] arr, int start, int end) {
int par = partion(arr, start, end);
// 若基准左边至少还存在两个数据,对这边的数据再找一次索引
if (par >= start + 1) {
quickTest (arr, start, par - 1);
}
// 若基准右边至少还存在两个数据,对这边的数据再找一次索引
if (par < end - 1) {
quickTest (arr, par + 1, end);
}
}
public static void main(String[] args) {
int[] arr = {20, 23, 12 , 14, 45, 2, 89, 100, 65, 77, 96};
quickTest(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
}
以上程序的输出结果是:[2, 12, 14, 20, 23, 45, 65, 77, 89, 96, 100]
找基准的过程是这样的:
快排的优化方案:当数据个数较少时,用直接插入排序效率较高:
public static void quickSort(int[] arr, int start, int end) {
if (end - start + 1 < 100) {
insertSort(arr);
return;
}
int par = partion(arr, start, end);
if (par > start + 1) {
quickSort (arr, start, par - 1);
}
if (par < end - 1) {
quickSort (arr, par + 1, end);
}
}