算法:快速排序与荷兰国旗问题


在聊快速排序之前,我们先解释一下荷兰国旗,即把一个数组分成三个部分,我们一般选最后一个元素作为基准值,即大于这个数的全部在左边,小于这个数的全部在右边,等于的在中间。
举个例子:arr{1,5,3,7,4,2,3,4},选取4做基准值,把他排成{1,3,2,3,4,4,7,5}大于小于区域的数顺序不要求。

荷兰国旗算法描述

首先第一步设less指针为-1,more指针为length-1。你可以想象成less是一个小于区域的右边界而more是大于区域的左边界。
在这里插入图片描述

然后把left指针所指的数和right指针所指的数进行比较。
如果arr[left]>arr[right],即比目标数大那么,arr[left]与less指针的下一个数交换,left+1。
在这里插入图片描述

如果arr[left]>arr[right],即比目标数大那么,arr[left]与more指针的前一个数交换,left不变,more-1。
在这里插入图片描述

在这里插入图片描述
直到最后left指针与more指针相遇,不能相等。比较结束,最后一步把一直没挪窝的基准值arr[right]放到arr[more](左边数第一个比基准值大的数)的位置上。
结束。

荷兰国旗代码展示

   static public int[] partion(int[] arr,int left,int right){
       int less = left-1;//小于区域右边界
       int more = right;//大于区域左边界
       //arr[right]是划分值
       while (left<more){//当前指针不可以超过more区域,因为里面的数字已经排好序了
           if (arr[left]<arr[right]){
               //小于标准值 当前值与小于区域右边第一个数交换 小于区域扩大1 left++
               ArrayUtils.swap(arr,++less,left++);
           }if (arr[left]>arr[right]){
                   //大于标准值
               ArrayUtils.swap(arr,--more,left);

           }else {
               //等于标准值
               left++;
           }

       }
       //因为由始至终标准值arr[right]都没有移动过
       // 所以现在就剩最后一步把right移动到大于区域左边界左侧的位置即等于区域的右边界
       ArrayUtils.swap(arr,more,right);
       return new int[]{less++,more};
   }

快排算法描述

有了前面荷兰国旗的基础,快排就是在荷兰国旗的基础上递归。先把一个数字用荷兰国旗的方法整理一遍,然后大于区域再做一次荷兰国旗,右边再做,一直做到数组只剩一个数,递归停止。
然而这样排序还是有一个缺陷就是如果最右侧的数字很小,两侧的数字不均匀会导致算法时间复杂度变差,针对这个问题我们可以随机选择一个数字来作为基准值,这样好和差的情况都会变成概率问题,算法时间复杂度为O(N*logN)

快排代码展示

    //先完成荷兰国旗的部分 快排是荷兰国旗的递归形式
   static public int[] partion(int[] arr,int left,int right){
       int less = left-1;//小于区域右边界
       int more = right;//大于区域左边界
       //arr[right]是划分值
       while (left<more){//当前指针不可以超过more区域,因为里面的数字已经排好序了
           if (arr[left]<arr[right]){
               //小于标准值 当前值与小于区域右边第一个数交换 小于区域扩大1 left++
               ArrayUtils.swap(arr,++less,left++);
           }if (arr[left]>arr[right]){
                   //大于标准值
               ArrayUtils.swap(arr,--more,left);

           }else {
               //等于标准值
               left++;
           }

       }
       //因为由始至终标准值arr[right]都没有移动过
       // 所以现在就剩最后一步把right移动到大于区域左边界左侧的位置即等于区域的右边界
       ArrayUtils.swap(arr,more,right);
       return new int[]{less++,more};
   }
//快排
    static public void quickSort(int[] arr){
        if(arr==null||arr.length<2){
            return ;
        }
        quickSort(arr,0,arr.length-1);
    }
    static public void quickSort(int[] arr,int L,int R){
       if(L<R){
           int[] partion = partion(arr, L, R);
           quickSort(arr,L,partion[0]-1);
           quickSort(arr,partion[1]+1,R);
       }
    }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值