快速排序模版(题目acwing:785)

 

 

 

#include<iostream>

using namespace std;

const int N=1e5+10;

int n;

int q[N];

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);

}

int main(){

    scanf("%d",&n);

    for(int i=0;i<n;i++)

    scanf("%d",&q[i]);

    quick_sort(q,0,n-1);

    for(int i=0;i<n;i++)

    printf("%d ",q[i]);

 

    return 0;

}

//思想:有三部分:选取分界点,调整区间,递归。注意选取分界点,选取分界点为中枢点,l+r>>1,位运算,等同(l+r)/2,要避免最坏情况:数组已经排好序时,假设1,2,3,4,5,6,选取q[l]为分界点时,上来i先++,等于l,q[i]=1,不小于1,i停;j先++,到j=r,因为有序,j先移动到6的位置,然后直到1的位置上,移动共6次,接下来分区间,l=j,第一部分递归结束,为空;第二部分递归j+1到r,也就是从2开始到6,排这五个数,依次递推,6+5+4+3+2+1移动基操,即时间复杂度O(N2);数都相等时为o(n)。所以为避免这种最坏情况,选取分界点为中枢点,l+r>>1.位运算,等同(l+r)/2;

 

给一组排序,肯定要为这组数据分配空间,即数组,而且此快排利用指针,要用到边界点,数组和两个边界点,快排函数参数

 

快排利用到递归,所以要有递归出口,快排函数首先就要写出口:一组数据经多次递归,直到排一个数据时,即l=r,或者排到递归为空,(此递归分配到的数组区间为空,没有数),if(l>=r)return;(排一个数或为空还需要排吗,直接return)

 

接下来调整区间(移动指针和交换数值)会用到分界点和两个指针,上来i=l-1,j=r=1;这样写是因为我们用的是do while写的判断移动指针,其特点是不管三七二十一,先do一下,那么我们为了让指针能够分别从边界点开始移动,直接先do一下,到l和r上,(如果i=l,j=r,先do一下,直接从l+1,r-1位置开始正式循环判断,遗漏了数据),相当于先do一下开始正式循环判断,i=l-1,j=r+1,先do一下,从l,r,开始判断。      交换数值条件,如果指针i,j相等,指向相同的数,没必要交换,i>j时,说明已经这次区间已经划分好了,交换的目的就是为了划分区间(使分界点左侧<=x,右侧>=x,(无论何时)),i<j时说明此次区间划分还在进行中,还没划分好,所以需要交换数值满足分界点两侧条件,就是说,交换数值条件:区间还没划分好我们需要交换数值,即i<j.

 

注意递归参数分界点的选取:快排属于分治算法,最怕的就是 n分成0和n,或 n分成n和0,这会造成无限划分

可以用i,这个分界点选取,像是划分好一次区间后j在i前面,那么用j划分的话就是l到j,j+1到r;用i就是l到i-1,i到r.可以利用1,2这组数据自己判断,会一直递归区间[0,1],出不来了。

但是x得是利用j写递归时分界点用x=q[l] i: q[r],对称的。或者都写中枢值不会有边界问题。

做算法题首先要看该题  目的,是排序还是其他等等,若是排序,肯定用相关算法解决,二看数据范围(判断时间复杂度)找合适的算法进行解。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值