快速排序实现心得及STL中sort源码理解

快排基本思路:

  1. 主元选择,这里直接选择第一个元素作为主元,可能导致时间复杂度为O(n),通常会从begin,mid,end选择中间元素做主元,同时对这三个元素进行排序(类似希尔排序)
  2. 双指针,将主元放在一边,这里将主元放在第一个元素(即位置不变),两个指针start和last,start为从begin+1开始从前往后走的指针,last为从end开始从后往前的指针。
  3. 遍历,start找到第一个大于主元的元素,end找到第一个小于主元的元素,交换两者位置。循环直到start大于last。
  4. 主元归位,跳出循环后,找到主元应该在的位置。
  5. 递归,对主元前的数据段进行快排,主元后的数据段进行快排

快排实现关键点

  • 当指针进行遍历时需要注意三种边界情况:1. 所有元素都比主元小。2. 所有元素都比主元大。3. 当指针碰到和主元一样大的元素时是否交换。
  • 主元归位是和last进行交换的原因:last最终停下来的位置一定是小于s[pivot]的位置或者就是pivot的位置(若与start交换可能因为,start停下来的位置是因为start==end)
  • 快排快的原因:每经历一次递归调用,该调用中的主元的位置都会确定,并不会在后续的调用中发生改变。
void quicksort(vector<int>& nums, int begin, int end)
{
     if(begin<end)
     {
         int pivot = nums[begin];//取第一个元素为主元
         swap(nums[begin], nums[end]);
         int idx=begin;
         for(int i=begin;i<end;++i)
         {
             if(nums[i]<pivot)
                 swap(nums[i], nums[idx++]);
         }
         swap(nums[idx], nums[end]);
         quicksort(nums, begin, idx-1);
         quicksort(nums, idx+1, end);
     }
         
 }

STL中的sort源码

其中几个tips

  • 快排是一个递归调用,为了防止栈被被过度使用(顺便提一下堆、栈、静态区的区别),所以要限制递归调用的深度
  • 为了递归调用的深度尽量小,所以要先处理主元前后短一点的数据段,因为先处理长一点的数据的话又会被更多次递归调用,加深递归深度。
  • sort总共涉及堆排序、快速排序、插入排序,

总结

源码中_ISORT_MAX是常量32,排序长度大于32时,会先进行快速排序,并用_Ideal参数限制快速排序递归调用的深度。每次while循环都会执行_Ideal = _Ideal*3/4。由于初始_Ideal值为排序长度N,所有限制的深度实际为Log(3/4)N。
当进行完一次快速排序,会将主元前后更短的数据进行递归调用,而更长的数据段用while循环进行处理
当多次递归调用快速排序且Ideal减小为0,若此时需要排序的数据段长度仍大于32时,就会调用堆排序,若在[2,32]之间,就会使用插入排序
在这里插入图片描述
个人的一些观点,有错误欢迎指正

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值