快速排序[原理,C++实现,注意事项,时间复杂度分析]

模板:

        

//本模板来自ACwing
void quick_sort(int q[],int l,int r)
{
    if(l>=r) return;
    
    int x=q[l+r>>1],i=l-1,j=r+1;
    
    while(i<j)
    {
        do i++;while(q[i]<x);
        do j--;while(q[j]>x);  
        if(i<j) swap(q[i],q[j]);
    }
    
    quick_sort(q,l,j);
    quick_sort(q,j+1,r);
};

原理:

       

注意事项:

(1)为什么while的循环控制条件一定不带等号?

        

        如果写成:

do i++;while(q[i]<=x);

        那么如果x恰好是待排序数组中最大的元素,那么while条件会一直成立,那么i将会一直走到头,j也是同理,如果选中的x恰好是数组中最小的元素,那么j一直走到头。

        所以,while的循环控制条件不带等号 

(2)为什么是do-while,不能用while 

        如果写成:

while(q[i]<x) i++;
while(q[j]>x) j--;

        设想这种情况,

        2…………2…………2

        x=2,i和j分别指向左右两边的2,那么两个while条件上来就不成立,i和j会无法移动,陷入死循环

(3)为什么交换q[i]和q[j]之前要判断i<j

        最终,i和j指针无非两种情况,

        1.相遇,相等

        2.穿过,错一

        设想案例:2,1,x=2,

        将1和2交换后,进入下一轮循环,因为是do-while,所以i和j又将各自前移一位,最终会形成此种情形

        如果swap前不检查i<j,那么此时又会swap,那么最终退出循环后,数组相当于没被排序,还是原样,

        swap前判断i<j,为防i j交叉

(4)递归区间和x的关系,

        如果x==q[i+j>>1],那么递归区间写quick_sort(q,l,j), quick_sort(q,j+1,r)

        如果x==q[i+j+1>>1],那么递归区间写quick_sort(q,l,i-1),quick_sort(q,i,r)

        为何不写quick_sort(q,l,j-1), quick_sort(q,j,r)?或者quick_sort(q,l,i),quick_sort(q,i+1,r)?

        因为满足<=x的,是 [l,i-1],[l,j] 区间,满足>=x的,是 [i,r],[j+1,r] 区间

        因为x=q[i+j>>1],可能会导致i=l,比如案例:1,2 ,此时如果递归区间写此时i=l,那么会发生[l,r]调用[l,r],也即死递归

               x=q[i+j+1>>1],可能会导致j=r,同样可举案例:1,2,同理。

总结:

        快排算法写错,一般只可能有两种情况:

        1.死循环

        

         这里的循环陷入死路,对应注意事项(2)

        2.死递归

        quick_sort(a,m,n)

                quick_sort(a,m,i-1)

                quick_sort(a,i,n)

         若i等于m,出现死递归

         quick_sort(a,m,n)

                quick_sort(a,m,j)

                quick_sort(a,j+1,n)

         而j=n,出现死递归

         

        对应注意事项(4)

时间复杂度分析:

        

例题: 

        掌握快速排序以后,可尝试解决以下题目练手:

        215. 数组中的第K个最大元素 - 力扣(LeetCode)

        912. 排序数组 - 力扣(LeetCode)

        786. 第k个数 - AcWing题库

        AcWing 785. 快速排序 - AcWing

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值