【数据结构与算法】快速排序

快速排序也使用了分治策略,它每次将待排序列分成两部分,前一部分的元素值都不比后一部分的元素值大。也就是前一部分都不比某个数大,后一部分都不比这个数小。这个基准的选择会直接影响快速排序的效率。
划分
固定第一个数为基准,以{5,4,3,5,6,12,11,-3,4,5,7}为例,用临时变量保存5,相当于挖了个坑,然后从后往前找到第一个小于基准的数,填入当前坑,原位置形成新坑,然后从前往后找到第一个大于基准的数继续填坑挖坑,最后将基准填入最后的坑。

基准为5,蓝色为左指针,红色为右指针操作
5,4,3,5,6,12,11,-3,4,5,7临时变量保存5,挖第一个坑
,4,3,5,6,12,11,-3,4,5,7从后往前找第一个小于5的
4,4,3,5,6,12,11,-3,,5,7填坑挖坑,从前往后找第一个大于5的
4,4,3,5,,12,11,-3,6,5,7填坑挖坑,从后往前找第一个小于5的
4,4,3,5,-3,12,11,,6,5,7填坑挖坑,从前往后找第一个大于5的
4,4,3,5,-3,,11,12,6,5,7停止挖坑
4,4,3,5,-3,5,11,12,6,5,7将5填入最后一个坑

可以看出不能保证与基准相等的元素会集中到某一边,也不能集中到基准附近

    private static int partition(int[] nums,int start,int end){
        int t=nums[start];
        int i=start,j=end;
        while(i<j){
            while(j>i&&nums[j]>=t){
                j--;
            }
            nums[i]=nums[j];
            while(i<j&&nums[i]<=t){
                i++;
            }   
            nums[j]=nums[i];
        }
        nums[i]=t;
        return i;
    }

如果基准位置为参数指定,代码为:

    private static int partition(int[] nums,int start,int end,int pivot){
        int t=nums[pivot]; //基准
        int pit=pivot; //坑的位置
        int i=start,j=end;
        while(i<j){
            while(j>i&&nums[j]>=t){
                j--;
            }
            nums[pit]=nums[j];
            pit=j;
            while(i<j&&nums[i]<=t){
                i++;
            }   
            nums[pit]=nums[i];
            pit=i;
        }
        nums[pit]=t;
        return pit;
    }

尝试很久写出不同思路的代码,但是好像没什么必要

    private static int partition(int[] nums,int start,int end){
        if(start>=end)return start;
        int t=nums[start];
        int i=start+1,j=end;
        while(i<j){
            while(nums[j]>=t&&j>i){  //从后往前找到第一个比t小的
                j--;
            }
            while(i<j&&nums[i]<t){   //从前往后找到第一个不比t小的,注意是不比t小
                i++;
            }
            if(i<j){
                Swap.swap(nums, i, j);
            }
        }
        //i有可能因为j的原因没有移动也没有比较
        if(nums[i]<t){
            Swap.swap(nums, start, i);
            return i;
        }else{ 
            return i-1;
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值