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


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

    这篇文章,是又一个故事的结束...
    lazy's story is continuing.
  • 相关阅读:
    1月27日 常用函数
    1月25日 JavaScript的DOM操作
    1月25日 JavaScript简介与语法
    1月24日 样式表案例
    5月14日 数字顺序打印并求和
    5月14日 根据班级人数,求平局分,最大值,最小值
    5月14日 九九乘法口诀
    5月14日 打印100以内与7有关的数
    5月14日 函数练习 100以内奇数的和
    5月14日 枚举类型
  • 原文地址:https://www.cnblogs.com/Hello-world-hello-lazy/p/13488644.html
Copyright © 2020-2023  润新知