算法——快速排序原理及其实现

#include <iostream>

#include <cstdio>

#include <ctime>

#include <cstdlib>

using namespace std;

//快速排序

/*

原理:取基准,比基准数小的放在左边,比基准数大的放在右边,递归

         另外,关于下文中提出的几个问题,在后面的手动推演中给出了答案

*/

int  a[9]={0,1,54,77,77,97,32,8,21};

int t[9];

void fun(int l,int r)

{

    if(l>=r) return;    //一开始给出递归停止的条件(l==r的条件是终止不了的,这是因为每次函数fun处理完以后l,p自增或者自减的缘故,当然也有可能l==r作为终止条件)

    int mid=a[(rand()%(r-l+1))+l];   

    int p=l,q=r;            //一般传进来的参量l,r不要动,引入别的变量代替l,r进行后面需要改动的操作

    //原数组中不好操作时,及时引入辅助数组t

   

    /*

    如果采用左右同时扫描,坐标找到一个比mid大的,右边找到一个比mid小的两者交换的思路的话,

    会发现不太好搞,因为左右这样符合条件的数不一定成对。

    所以思路上采用:扫描原来的整个数组,碰到比mid小的,从左边放入辅助数组t,碰到比mid大的,

    从右边放入辅助数组t。

    */

   

    for(int i=l;i<=r;i++) //开始扫描

    {

        if(a[i]<mid)       //按顺序放入t数组,这里不能取a[i]<=mid,,必须把等于mid的情况放在下一个for循环中,否则递归不完

            t[p++]=a[i];

        if(a[i]>mid)

            t[q--]=a[i];

    }

    for(int i=p;i<=q;i++)   //剩下的都和mid一样大(这里p和q都取=的原因在于上一步中p,q的后置运算符)

        t[i]=mid;

    for(int i=l;i<=r;i++)//就从功能单元的角度理解,这一步是不能少的(不要从一次次的递归嵌套理解)

        a[i]=t[i];

    fun(l,p-1);     //p-1说明中间那一部分和mid一样大的元素不用管了

    fun(q+1,r);

    /*  无论基准值是不是随机的,p-1和q+1都不能变,否则递归结束不了。因为如果不管p,q的后置运算符,那么那么在下一次的递归中,开辟的数组范围就会变*/

}

int main()

{

    fun(1,8);

    for(int i=1;i<=8;i++)

        cout<<a[i]<<" ";

    return 0;

}

 

另外补充一点:mid之所以取随机值是为了降低复杂度,达到O(nlogn)

posted @ 2020-08-12 08:54  py佐料  阅读(123)  评论(0编辑  收藏  举报