将基准值保存到另一个变量里,该位置上的数据就可以直接覆盖。
一轮过后的结果是,基准值在正确的位置上,左边都是比它小的,右边都是大于等于它的。
然后递归左半边,递归右半边。
正常版quickSort
稍微简单版ss
ss加上判断之后,递归比quickSort少了六分之五
public static void main(String[] args) {
int[] nums1 = new int[]{2,3,2,6,4,8,0,20,18,59};
ss(nums1, 0, nums1.length - 1);
System.out.println("ss " + Arrays.toString(nums1));
int[] nums2 = new int[]{2,3,2,6,4,8,0,20,18,59};
quickSort(nums2, 0, nums2.length - 1);
System.out.println("quickSort" + Arrays.toString(nums2));
}
public static void ss(int[] nums, int l, int r){
if (l >= r) {
return;
}
//设mind为基准值
int mind = nums[l], i = l, j = r;
while (i < j) {
while (i < j && nums[j] > mind){
j--;
}
//覆盖时加上判断,防止最后跳出时i!=j,这样也可以少一些不必要的递归
if (i < j){
nums[i++] = nums[j];
}
while (i < j && nums[i] < mind) {
i++;
}
if (i < j) {
nums[j--] = nums[i];
}
}
//跳出的情况是i==j,这个位置就是排序后基准值应该在的位置
nums[i] = mind;
//因为i的位置上已经是正确的位置,所以就不用再判断.
//递归左半边
ss(nums, l, i - 1);
//递归右半边.因为i==j这里也可以时i+1到r
ss(nums, j + 1, r);
}
public static void quickSort(int[] arr, int start, int end) {
//提出基准值,因为循环的时候这个位置会被覆盖.
int pivot = arr[start];
int i = start;
int j = end;
while (i < j) {
//从后往前,遇到小于等于基准值的时候停止
while (i < j && arr[j] > pivot) {
j--;
}
//覆盖
arr[i] = arr[j];
//覆盖后小于等于基准值的值会在应该在的那一边,所以i位置上不用再考虑
i++;
//从前往后,遇到大于等于基准值的时候停止
while (i < j && arr[i] < pivot){
i++;
}
//覆盖
arr[j] = arr[i];
//覆盖后,大于基准值的值的值会在应该在的一边,所以j位置上不用再考虑
j--;
}
//i位置上就是基准值应该在的位置
arr[i] = pivot;
if (i - 1 > start) {
quickSort(arr, start, i - 1);
}
if (j + 1 < end) {
//注意这里是j+1
quickSort(arr, j + 1, end);
}
}