快速排序的一些典型算法

快速排序的一些典型算法

常规写法,未随机选取pivot

    vector<int>sortArray(vector<int>&nums)
    {
        quickSorts2(nums,0,nums.size()-1);
        return nums;
    }

    void quickSorts(vector<int>&nums,int left,int right)
    {   
        //当左边大于右边,那么就可以跳出循环
        if(left>=right)
        {
            return;
        }

        //设定划分的元素的值
        int pivotIndex=partitionDouble(nums,left,right);

        //继续递归进行排序
        quickSorts(nums,left,pivotIndex-1);
        quickSorts(nums,pivotIndex+1,right);
    }

//寻找目标的中枢值
    int partition(vector<int>&nums,int left,int right)
    {
        //选择切分的元素
        int pivot=nums[left];

        // 将pivot后面的元素划分成两个区间
        // all in nums[left+1,j]<=pivot
        //all in nums (j,i)>pivot
        //遍历区间中的所有元素
        //初始化 j 的值,使得两个区间初始化的时候都为空区间
        //j位于第一个区间的最后一个元素
        int j=left;
    
        for(int i=left+1;i<=right;i++)
        {//大放过,小交换到前面
            if(nums[i]<pivot)
            {
                //先将j++
                j++;
                swap(nums,i,j);
            }
        }
        swap(nums,left,j);
        return j;

    }

    void swap(vector<int>&nums,int index1,int index2)
    {
        int temp=nums[index1];
        nums[index1]=nums[index2];
        nums[index2]=temp;
    }

随机选用区间元素,降低对于顺序数组的时间复杂度

//寻找目标的中枢值
    int partition2(vector<int>&nums,int left,int right)
    {
        //随机选择
        randomPartiton(nums,left,right);
        //选择切分的元素
        int pivot=nums[left];

        // 将pivot后面的元素划分成两个区间
        // all in nums[left+1,j)<=pivot
        //all in nums [j,i)>pivot
        //遍历区间中的所有元素
        //初始化 j 的值,使得两个区间初始化的时候都为空区间
        //j位于第二个区间的第一个元素
        int j=left+1;
    
        for(int i=left+1;i<=right;i++)
        {//大放过,小交换到前面
            if(nums[i]<pivot)
            {
                //先将j++
                swap(nums,i,j);
                j++;
            }
        }
        swap(nums,left,j-1);
        return j-1;

    }

    void swap(vector<int>&nums,int index1,int index2)
    {
        int temp=nums[index1];
        nums[index1]=nums[index2];
        nums[index2]=temp;
    }
    

    //划分在顺序数组和逆序数组上表现很差的
    //解决方法随机选择切分元素

    void randomPartiton(vector<int>&nums,int left,int right)
    {
        int i=left+rand()%(right-left+1);
        swap(nums,i,left);
    }

双路快排


    //双路快排:把与pivot相等的元素平均分到数组的两侧
    //左边:遇到严格小于pivot的元素则纳入左边区间,否则停下
    //右边:遇到严格大于pivot的元素则纳入右边区间,否则停下
    //交换,左边区间和右边区间各增加一个元素
    //等于pivot的元素,通过交换,平均地来到了数组两边

//寻找目标的中枢值
    int partitionDouble(vector<int>&nums,int left,int right)
    {
        randomPartiton(nums,left,right);
        //选择切分的元素
        int pivot=nums[left];

        // 将pivot后面的元素划分成两个区间
        //all in nums[left+1,le)<=pivot;
        //all in nums(ge,right]>=pivot;

        //设置le和ge的初值,使得,两歌区间初始化为空区间
        int le=left+1; //le:less equals
        int ge=right; //ge:greate eauqls


        while(true)
        {
            //遇到比pivot的大的时候停下来
            while(le<=ge&&nums[le]<pivot)
            {
                le++;
            }
            //遇到比pivot的小的时候停下来
            while(le<=ge&&nums[ge]>pivot)
            {
                ge--;
            }

            if(le>=ge)
            {
                break;
            }

            //le 来到了第一个大于等于pivot的位置
            //ge 来到了第一个小于pivot的位置

            swap(nums,le,ge);
            le++;
            ge--;

        }
        
        swap(nums,left,ge);
        return ge;
    }

三路快排

//三路快排,把与pivot相等的元素挤到中间

    //情况1:当看到的元素<piviot时,把它交换到 等于pivot的区间 的第一个位置
    //情况2:当看到的元素=pivot时,什么都不用做,看下一个元素
    //情况3:当看到的元素>pivot时,把它交换到大于pivot的区间的前一个位置

    //好处,把数值相等的元素挤到中间,每一次可以使得确定的元素变多,以后递归处理的区间长度变少了
    
    void quickSorts2(vector<int>&nums,int left,int right)
    {   
        //当左边大于右边,那么就可以跳出循环
        if(left>=right)
        {
            return;
        }

        randomPartiton(nums,left,right);
        int pivot=nums[left];

        // 将pivot后面的元素划分成三个区间
        //all in nums[left+1,lt)<pivot;
        //all in nums[lt,i)=pivot;
        //all in nums(gt,right]>pivot;

        //设定边界的初始条件
        int lt=left+1;//lt=less than
        int gt=right; //gt= greater than
        int i=left+1;

        while(i<=gt)
        {
            //当元素小于当前划分的值时
            if(nums[i]<pivot)
            {
                //交换到等于pivot区间的第一个位置
                swap(nums,i,lt);
                lt++;
                i++;
            }
            else if(nums[i]==pivot)
            {
                //划分在第二个区间里
                i++;
            }
            else{
                 //划分到数组的末尾
                 swap(nums,i,gt);
                 gt--;   
            }
        }
        //交换 pivot
        swap(nums,left,lt-1);



        //继续递归进行排序
        quickSorts2(nums,left,lt-2);
        quickSorts2(nums,gt+1,right);
    }
};

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值