简单写个快排

         对于时间复杂度为O(nlogn)的高级排序算法,虽然排序原理了解,但是落实到代码上还是会有一写生疏,最近在刷leetcode时候看到一个排序题,所以有重新研究了一下快排的代码,想学习或者重温排序算法,可以去这里练习。快速排序使用了分治的思想,先选取一个主原pivot,比主原小的放在左边,比主原大的放在右边,在递归的对左边和右边进行同样的操作,最后就可以得到一个有序数组,关于排序的算法,可以参看我之前的文章,里边介绍了各种排序算法的操作步骤,配合动图可以快速的理解。

        快排首先要选取主原,主原的选取会直接影响算法的性能,慕课上浙大数据结构中,主原选取的是数组前中后三个数的中位数作为主原

         如果仅仅用于刷题我们可以使用随机数来选取主原,虽然随机数的生成也会耗时,但是作为刷题或者面试,我们只要展示出选取主原的思想就可以了。

        我们首先使用随机数生成函数rand()%(r-l+1)产生一个在0到数组长度之间的整数,代表主原的位置,然后,把主原放在数组的最右边,之后定义两个指针i,j同时指向数组的初始位置,j一直向后遍历,如果遍历的值小于主原,那么与i与j交换,同时i指向下一个需要交换的位置,注意i所指的位置是大于主原的,他代表下一个小于主原的值变换后的位置,i左边都小于主原。因为最后一个是主原,当j遍历到倒数第二个值则停止遍历,我们看一下此时的i指针是大于主原的,所以将i和主原nums[r]位置互换,这样i的位置左边小于主原,右边大于主原,第一趟分治结束,之后对左边的和右边的部分数组分别进行递归,得到有序数组nums。

代码如下:

class Solution {
public:
    void qsort(vector<int>& nums , int l ,int r){
        //递归终止条件,如果左边界不小于右边界,递归终止
        if(l>=r)    return;   
        //通过随机数选取主原位置,主原值为povit
        int pos = rand()%(r-l+1) + l , povit = nums[pos];
        //将主原放在数组最右边
        swap(nums[pos],nums[r]);
        //定义两只指针i,j 都指向数组的最左端
        int i =l;
        //如果当前值小于主原,则当前位置与i互换,i自增指向下一个要互换的位置
        for(int j= l ; j<r;j++){
            if(nums[j] < povit){
                swap(nums[i], nums[j]);
                i++;
            }
        }
        //将主原和i互换,此时完成一趟操作,i左边小于主原,i右边大于主原
        swap(nums[i],nums[r]);
        //对左右两个子数组进行同样的操作
        qsort(nums,l,i-1);
        qsort(nums,i+1,r);
    }

    vector<int> sortArray(vector<int>& nums) {
        //随机数种子
        srand(time(0));
        //调用快排函数
        qsort(nums,0,nums.size()-1);
        return nums;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值