一个优雅的三路快排

思路同75、颜色分类,将整个数组分为三段,小于aa,等于aa,大于aa,其中aa是在数组中随机取的一个数。

1、设置两个指针,l记录第一个非小于aa的位置,l左边比aa小,r记录最后一个非大于aa的位置,r右边比aa大。然后使用i从头到尾扫一遍,nums[i]遇到比aa小的数就和nums[l]互换,遇到比aa大的数就和nums[r]互换,遇到aa就跳过,直到i>r停止(i要将nums[r])处理完。

2、当处理完时:[0,left)-->比aa小的数; [left,right]-->aa; (right,n-1]-->比aa大的数。继续对[0,left), 和(right,n-1]两段采用同样的方法排序。

需要注意的是:
(1)当遇到比aa大的数,换回来的可能是比aa小的数(或者aa),i不能前进,因为如果比aa小,l在i前面,i前面会有aa,要继续交换;

(2)当遇到比aa小的数,换回来的一定是aa(除非i==l,这个时候相当于原地不动),无论哪种情况,i都要前进。

由此该数组分为4段:[0,left)-->比aa小的数; [left,i)-->aa; [i,right]-->乱序; (right,n-1]-->比aa大的数。

    void mysort(vector<int>& nums, int first, int last){
        if(first>=last) return;
        int x=first+rand() % (last-first+1), aa=nums[x], l=first, r=last, i=first;
        while(i<=r){
            if(nums[i]>aa){
                swap(nums[i], nums[r]);
                --r;
            }
            else if(nums[i]==aa) ++i;
            else{
                swap(nums[i], nums[l]);
                ++i; 
                ++l;
            }
        }
        mysort(nums, first, l-1);
        mysort(nums, r+1, last);
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值