Java里的Arrays有一个sort()方法,具体的排序细节就是使用快速排序进行的实现,它是一个不稳定的,追求排序速度的排序算法 ,时间复杂度O(N* logN)
它与归并的思路有相近之处,都是先保证局部有序,再保证整体有序
在引入快速排序前,需要先去引导出两个问题
例1,数组[2,1,3,4,5,1,3],k=3,返回 [2,1,1,3,3,4,5]即可
例2,数组[2,1,4,2,4,5,3,6],k=6.返回原数组即可
public static void main (String[] args) {
int[] arr = new int[]{1, 4, 76, 2, 3, 673, 5, 6, 73, 7, 9, 9, 8};
new PartitionSort().partition(arr, 0, arr.length - 1);
for (int i : arr) {
System.out.printf(i + ",");
}
}
public int partition (int[] arr, int left, int right) {
if (left > right) {
return -1;
}
if (left == right) {
return left;
}
// 左边界
int leftIndex = left - 1;
//对数
int num = arr[right];
for (int i = left; i < right; i++) {
//只要当前数小于等于对数,与小于区相邻的数交换
if (arr[i] <= num) {
//++left即小于区的相邻数
swap(arr, ++leftIndex, i);
}
}
swap(arr, ++leftIndex, right);
return leftIndex;
}
即如何在上一题的基础上,将数组分为三块,小于区,等于区,大于区
比较0号位与7号位,9大于5,向大于区左侧进行交换,即交换0号位与6号位,大于区左移。
交换完有个细节,就是索引不加一,保持原位不动
public int[] sort (int[] arr, int left, int right) {
if (arr == null || right - left < 2) {
return new int[]{-1, -1};
}
int num = arr[right];
int position = left;
int leftIndex = left - 1;
int rightIndex = right;
while (position <= rightIndex) {
if (arr[position] < num) {
swap(arr, position++, ++leftIndex);
} else if (arr[position] > num) {
swap(arr, position, --rightIndex);
} else {
position++;
}
}
swap(arr, arr.length - 1, rightIndex);
return new int[]{leftIndex, rightIndex};
}
从荷兰国旗问题中可以看出,给定一个数组,我可以在O(N)复杂度内,让他在某一小块上有序,即等于区的起止点,因此结合归并的思想,只要让每一小块排序都能确定出一部分以后不再需要排序的序列,合并后就是一个完整的排好序的集合
public void quickSort (int[] arr, int left, int right) {
if (left >= right) {
return;
}
int[] partition = partition(arr, left, right);
quickSort(arr, left, partition[0] - 1);
quickSort(arr, partition[1] + 1, right);
}
private int[] partition (int[] arr, int left, int right) {
if (right > left + 1) {
int randomIndex = RANDOM.nextInt(right - left) + left;
swap(arr, randomIndex, right);
}
int num = arr[right];
int position = left;
int leftIndex = left - 1;
int rightIndex = right;
while (position < rightIndex) {
if (arr[position] < num) {
swap(arr, position++, ++leftIndex);
} else if (arr[position] > num) {
swap(arr, position, --rightIndex);
} else {
position++;
}
}
swap(arr, right, rightIndex);
return new int[]{leftIndex + 1, rightIndex - 1};
}