快速排序左右指针移动顺序问题

闲来无事,突然想敲一下快排,这一敲不当紧,问题接踵而至,以前怎么就没有发现过这个问题呢......说明没有思考[笑哭]

目录

1.快排核心思想

2.快排Java实现(指针移动问题)

3.快排Java实现(问题解决)


1.快排核心思想

  • 选择基准值(一般将数组第一个数作为基准值);
  • 双指针分别从左右两边移动,左边寻找比基准值大的数,右边找比基准值小的数。 两者交换数值;
  • 左指针==右指针时,将 基准值 与 指针所指位置 交换数值;
  • 左指针==右指针,将数组分成两部分,分别重复上述操作即可。

2.快排Java实现(指针移动问题)

注意:下边代码先移动左边指针,然后移动右边指针。排序的结果是错误的。

import java.util.Arrays;

public class QuickSort {
    public static void main(String[] args) {
        int[] arr = {5, 3, 6, 2, 9, 4, 7, 10, 1, 8};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }

    public static void quickSort(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        //双指针,l左指针,r右指针
        int l = left, r = right;
        //选择数组第一个数作为基准值
        int key = arr[l];
        //此处先移动左指针
        while (l < r) {
            //移动左指针,寻找比基准值大的数
            while (l < r && arr[l] <= key) {
                l++;
            }
            //移动右指针,寻找比基准值小的数
            while (l < r && arr[r] >= key) {
                r--;
            }
            //交换找到的两个符合条件的值
            if (l < r) {
                int temp = arr[l];
                arr[l] = arr[r];
                arr[r] = temp;
            }
        }
        //将基准值与指针位置数交换
        arr[left] = arr[l];
        arr[l] = key;
        //递归处理数组左边部分
        quickSort(arr, left, l - 1);
        //递归处理数组右边部分
        quickSort(arr, l + 1, right);
    }
}

 排序结果:

大家可以手推一趟快速排序,先移动左指针,很容易就能发现问题,最后交换基准值时,指针位置的值比基准值大

但是根据我们所学可知,每次快排都会将数组分成左边数组的数值 全部小于 右边数组的数值才对。

解释:

如果先移动左指针就导致每次交换基准值时,都将会把比基准值大的数移动到了左边数组的第一个数,导致左边数组的值不完全小于右边数组的值,递归快排都将出错。

3.快排Java实现(问题解决)

解决:先移动右指针即可;每次交换基准值时都将比基准值小的数移动到左边待排数组的第一个数

import java.util.Arrays;

public class QuickSort {
    public static void main(String[] args) {
        int[] arr = {5, 3, 6, 2, 9, 4, 7, 10, 1, 8};
        System.out.println("排序前:"+Arrays.toString(arr));
        quickSort(arr, 0, arr.length - 1);
        System.out.println("排序后:"+Arrays.toString(arr));
    }

    public static void quickSort(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        //双指针,l左指针,r右指针
        int l = left, r = right;
        //选择数组第一个数作为基准值
        int key = arr[l];
        //先移动右指针
        while (l < r) {
            //移动右指针,寻找比基准值小的数
            while (l < r && arr[r] >= key) {
                r--;
            }
            //移动左指针,寻找比基准值大的数
            while (l < r && arr[l] <= key) {
                l++;
            }
            //交换找到的两个符合条件的值
            if (l < r) {
                int temp = arr[l];
                arr[l] = arr[r];
                arr[r] = temp;
            }
        }
        //将基准值与指针位置数交换
        arr[left] = arr[l];
        arr[l] = key;
        //递归处理数组左边部分
        quickSort(arr, left, l - 1);
        //递归处理数组右边部分
        quickSort(arr, l + 1, right);
    }
}


结果: 

错误百出---小菜一枚

 

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值