• 快速排序


    他的思想是找到一个值,小的放在他的左面,大的放在他的右面。

    这样左右两边都只需要在自己的范围内比较了

    一般用递归来实现

    快速排序和其他基于比较的排序方法来说 比较次数少

    下面是没有优化的快排代码

    void QuickSort(int arr[],int nLow,int nHigh)
    {
        if(arr == NULL || nLow >= nHigh)return;
    
        //标准值,标准值左侧都小于它,右侧都大于它
        int nStandard;
        nStandard = Sort(arr,nLow,nHigh);
    
        //递归,排序标准值的左面和右面
        QuickSort(arr,nLow,nStandard-1);
        QuickSort(arr,nStandard+1,nHigh);    
    }

    其中Sort的代码如下:

    利用的是挖坑填补法,把数组第一个参数的位置当做标准值

    int Sort(int arr[],int nLow,int nHigh)
    {   
        int temp;
        temp = arr[nLow];
        while(nLow < nHigh)
        {
            //从后向前找比标准值小的
            while(nLow < nHigh)
            {
                if(arr[nHigh] < temp)
                {
                    //放前面
                    arr[nLow] = arr[nHigh];
                    nLow++;
                    break;
                }
                nHigh--;
            }
            //从前向后找比标准值大的
            while(nLow < nHigh)
            {
                if(arr[nLow] > temp)
                {
                    //放后面
                    arr[nHigh] = arr[nLow];
                    nHigh--;
                    break;
                }
                nLow++;
            }
        }
        
        //标准值放入
        arr[nLow] = temp;
        return nLow;
    }

     优化1

    上面这种写法是两个while的嵌套,效率非常低

    所以我们想到下面这种写法,一层循环就可以了,用区间分割法

    int Sort(int arr[],int nLow,int nHigh)
    {   
        //小于标准值的数组下标
        int nSmall;
        nSmall = nLow-1;
        //把数组最后一个元素当做标准值
        for(nLow;nLow<nHigh;nLow++)
        {
            //如果数组当前元素比标准值小,小于标准值的数组下标++
            if(arr[nLow] < arr[nHigh])
            {
                //如果数组当前元素前面有≥标准值的,将≥标准值的那个与当前元素交换
                if(++nSmall != nLow)
                {
                    arr[nLow] = arr[nSmall]^arr[nLow];
                    arr[nSmall] = arr[nSmall]^arr[nLow];
                    arr[nLow] = arr[nSmall]^arr[nLow];
                }
            }
        }
    
        //标准值放入
        if(++nSmall != nHigh)
        {
            arr[nSmall] = arr[nSmall]^arr[nHigh];
            arr[nHigh] = arr[nSmall]^arr[nHigh];
            arr[nSmall] = arr[nSmall]^arr[nHigh];
        }
    
        return nSmall;
    }      

     这种写法有几个比标准值小的small就++几次,最后small等于最后一个比标准值小的数组下标

    将small后一个的元素与标准值交换 这样就能做到标准值左面都比它大,右边都比它小

    优化2

    快速排序如果你找到的标准值是整个数组的最大值或者最小值,那么它就没办法将数组分成两部分

    或者说你取得值很大或很小都不利于我们快排

    所以我们可以在数组中取第一个,中间一个,最后一个,找到他们三个之中的中位数

    进而减小遇到这种情况的概率

    代码实现上可以找到之后将中位数与最后一个数进行交换,重复优化1的步骤

    优化3

    频繁的调用递归会降低系统的效率 我们可以借助辅助栈和循环来代替递归

    代码在下面

    void QuickSort(int arr[],int nLow,int nHigh)
    {
        if(arr == NULL || nLow >= nHigh)return;
    
        Stack* st = NULL;
        s_Init(&st);
        //栈里装的是数组的高低下标
        s_Push(st,nLow,nHigh);
        int low,high;
    
        //因为low和high在变化,用a,b记录他们
        int a,b;
    
        //小于标准值的数组下标
        int nSmall;
        while(st->nCount != 0)
        {
            s_Pop(st,&low,&high);
            a = low;
            b = high;
            nSmall = low-1;
            //把数组最后一个元素当做标准值
            for(low;low<high;low++)
            {
                //如果数组当前元素比标准值小,小于标准值的数组下标++
                if(arr[low] < arr[high])
                {
                    //如果数组当前元素前面有≥标准值的,将≥标准值的那个与当前元素交换
                    if(++nSmall != low)
                    {
                        arr[low] = arr[nSmall]^arr[low];
                        arr[nSmall] = arr[nSmall]^arr[low];
                        arr[low] = arr[nSmall]^arr[low];
                    }
                }
            }
            //标准值放入
            if(++nSmall != high)
            {
                arr[nSmall] = arr[nSmall]^arr[high];
                arr[high] = arr[nSmall]^arr[high];
                arr[nSmall] = arr[nSmall]^arr[high];
            }
            //判断是否入栈
            if(nSmall-1 >= a)
                s_Push(st,a,nSmall-1);
            if(b >= nSmall+1)
                s_Push(st,nSmall+1,b);
        }
    }

    优化4

    快速排序中如果元素个数很小(小于等于3),可以将快速排序改为插入排序

    插入排序前面有介绍,就不写代码了

  • 相关阅读:
    Xshell连接virtualbox下的fedora虚拟机
    异常:java.sql.SQLIntegrityConstraintViolationException: Column 'category' cannot be null
    JQuery中获取表中的数据
    关于springboot报错:新建springboot项目报错:Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
    IDEA设置
    java基础总结
    JavaWeb----Servler
    IDEA2020版使用
    Java面向对象
    【CMU 6.824】 RPC & Threads
  • 原文地址:https://www.cnblogs.com/TheQi/p/9103763.html
Copyright © 2020-2023  润新知