图解快速排序算法-02

图解快速排序算法(补充)

        关于快速排序算法的两种实现(split、partition)在上一篇”快速排序算法的两种Java实现及图解“中已经通过图示详细说明,并且也附上了Java代码。

        但是,第二种实现方法(partition)的代码中有一点需要注意的,没有强调,并且也没有给予解释。

    /**
     * (6)-6.2 快速排序
     * 双指针方法-partition
     * @param arr
     * @param low    // start
     * @param high   // end
     * @return
     */
    public static int[] quickSort2(int arr[], int low, int high)
    {
        if(low < high)
        {
            int i = partition(arr, low, high);    //划分数组并获取比较元素的位置
            quickSort2(arr, low, i-1);     //对比较元素左边进行排序
            quickSort2(arr, i+1, high);     //对比较元素右边进行排序
        }
        return arr;
    }
    //划分数组
    public static int partition(int arr[], int low, int high)
    {
        int x = arr[low];    //将该数组第一个元素设置为比较元素
        int i=low;
        int j=high;
        while(i < j)
        {
            while(i<j && arr[j] >= x)
                j--;     //从右至左找到第一个小于比较元素的数
            while(i<j && arr[i] <= x)
                i++;     //从左至右找到第一个大于比较元素的数
            /*需要注意的是,这里的j--与i++的顺序不可以调换!
             *如果调换了顺序,i会走过头,以至于将后面较大的元素交换到数组开头*/

            //将大数与小数交换
            if(i!=j)
                swap(arr, i, j);
        }
        swap(arr, i, low);    //将比较元素交换到期望位置
        return i;     //返回比较元素的位置
    }
    //交换函数
    public static void swap(int arr[], int i, int j)
    {
        int t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

NOTE:

*需要注意的是,这里的j--与i++的顺序不可以调换!
*如果调换了顺序,i会走过头,以至于将后面较大的元素交换到数组开头。
            while(i<j && arr[j] >= x)
                j--;     //从右至左找到第一个小于比较元素的数
            while(i<j && arr[i] <= x)
                i++;     //从左至右找到第一个大于比较元素的数

这两句话什么意思呢?为什么互换了会走过头?(请看如下图例)

拿无序数组[5,3,2,1,4,6,7] 为例:

        上图这种情况就是将”i++“放在”j--“之前的后果。i走过了头,将比”基准值“(or比较元素5)更大的6交换到了数组开头!显然这种情况是我们不想看到的。

接着,看一下先移动指针 j 会有怎样的结果:

比较上边两种情况,其实对于指针 j 来说,没有”过头“的概念,即使称之为”过头“了,最终与”基准值“相交换 换到数组开头的也是一个小于”基准值“(这里<5)的元素,所以”j--“在前对结果无影响,但是若”i++“在前则会排序错误。

参考:

十大经典排序算法: https://www.jianshu.com/p/c1efd6a8bb95 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值