快速排序

快速排序

一、核心思想

​ 递归;二分(分治)

二、算法实现

1、 选标杆 x 定两边 左l右r
2、 设计算法来实现 <=x的在左边,>=x的在右边(前提 升序)
	可采用“双指针”:
		① 左边 i 右边 r (前提是 i<j 作为合法条件)
		② 左右两边都开始寻找直到不满足划分条件时,“停下”
		③ 交换i r (i<j)
		④ 一旦i<j不合法 则结束循环
3、 递归

三、代码实现

//首先,指明出现无限划分的情况————
//划分后的数据的数量:左0右n,或者左n右0
//(主要是因为数量为n的区间,如果数量为0则会被递归结束条件直接return)

void quick_sort(int q[], int l, int r)
    {
    	//递归一定要设置 递归结束条件
        //l>=r很显然,此时所划分的区间只有一个数或者没有数
    	if(l >= r) return;	
    	
    	//实现区间内的排序
    		//i=l-1 对应着下面循环语句中的i++,便于语句的书写,同时也能进入下方循环
            /*
            x的取值与划分区间的边界有关,
            一般选取中间位置的值(>>1右移1就是/2),或者随机取值(前提是不影响边界)
            */
        int i = l - 1, j = r + 1, x = q[l + r >> 1];
        
    	//此处i<j,不可以取= ,
    	//当i==j时,有可能因为数组越界而导致奇奇怪怪的问题(可以模拟{0,1})
        while(i < j)
        {
            
            //左右两边都开始寻找直到不满足划分条件时,“停下”
                /*
                while(q[i] < x)中 不能取=x 的情况
                当数据全部相等时可能会出现无限划分的情况
                */
            do i++; while(q[i] < x);
            do j--; while(q[j] > x);
            
            //此处if(i < j),可以取=
            if(i < j) swap(q[i], q[j]);
        }

    	//递归再细化
    	/*
    	注意边界问题可能造成的无限划分:
            ① 最容易写错的一个错误写法就是左边l到r,右边j到r————
                模拟{0,1}可知:第一次划分区间为{0},{0,1}(q[i]=0,q[j]=0)
                于是右侧区间数量成为n,开始无限划分
            所以为了使划分的区间是不重叠的,因此要选择一个指针和该指针的下一个作为边界
            ② 此时会引出另一个问题,比如选择j,那x的位置不能选择r——
                第一次划分也许{...<=q[r]}{q[r]>=...}
                第二次划分对于右侧来说x会变成最右边的数据
                  但是左侧依旧是q[r],左侧始终满足<=q[r],则后续划分还将是左侧数据开始无限划分
        因此一般 x取中间位置的数据(注意是中间位置,而不是中间值)
           边界选取j与j+1
        */
        quick_sort(q, l, j), quick_sort(q, j + 1, r);
    }
int main()
{
    int a[50]={0,1},n=2;
    //数组a,下标0,n-1
    quick_sort(a,0,n-1);
    for(ll i=0;i<n;i++){
      cout<<a[i]<<"   ";
    }
}

四、注意

但实际上由于 C++ algorithm 库中已经自带 std::sort 函数,你并不需要手写快排。

std::sort在快排的基础上加入了一些优化,比如在分治达到一定深度时改用堆排序,从而使得最差时间复杂度为 O(nlogn*) 。因此,你手写快排也只会被 std::sort 慢

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值