• 快速排序


     参考:https://blog.csdn.net/morewindows/article/details/6684558

     

    正如文中所说,最好能用自己的话总结算法过程(思路),这样印象深刻,有助于理解。

    快排序也称为分治法,更恰当地说是挖坑填数+分治法

    挖坑填数:

    设置头尾两个指针,初始i=0,j=size-1。

    选定一个基准数,可以是数组第一个值(即i处数值),将其赋值给临时变量x。由于将该值保存了下来,就相当于在原数组对应位置处挖了一个坑,可以将其他数值填进来。

    从尾部开始寻找小于x的数值,将其赋值给A【i】。即用A【j】填上一步 i 处的坑,同时,j 处形成了新的坑。

    从头部开始寻找大于等于x的数值,将其赋值给A【j】。即用A【i】填上一步 j 处的坑,同时,i 处又形成了新的坑。

    重复上述挖坑填坑过程直到两根指针相等 i==j,此时i(j)左侧都是小于x的数,右侧都是大于等于x的数,并且 i 处形成新的坑,将 x 值填进来。

    然后分治,对  左侧第一个数 ~ i-1   与    i+1 ~ 右侧最后一个数  这两个区间重复上述过程,直到传入的头尾指针相等。

     

    核心代码:

    void qSort(vector<int> &A,int l,int r)
    {
        if (l>=r)
        {
            return ;
        }
        int x=A[l];//取A[l]为基准,也就是第一个坑;
        int i=l,j=r;
        while(i<j)
        {
            //从右向左找小于x的数,填入坑中;
            while(i<j&&A[j]>=x)
            {
                j--;
            }
            if (i<j)
            {
                A[i]=A[j];//A[j]填入坑中,j处形成新的坑;
                i++;
            }
            //从左向右找大于等于x的数,填入坑中;
            while(i<j&&A[i]<x)
            {
                i++;
            }
            if (i<j)
            {
                A[j]=A[i];//A[i]填入坑中,i处形成新的坑;
                j--;
            }
        }
        //循环结束时,i==j,将x填入坑中;
        A[i]=x;
        qSort(A,l,i-1);
        qSort(A,i+1,r);
    }

     

     PS:关于元素相等情况的分析。

    假设是大于等于(小于等于前移情况同理)基准X的数向后移,某个等于基准的数,被填到了基准确定位置id的后面,比如end。

    则下一次分治时,在右侧区间,即在【id+1,end】这个区间完成挖坑填数时,以id+1对应的数为基准。

    注意,该数一定是大于等于上一个X也就是当前end对应的值。若大于,end处值小于当前基准,被填坑到了前面,是正确的升序。若等于,相当于重复前面的分析,end处值一定会被填到比它大的数的前面,除非右侧区间全部是相同的数。如果右侧区间全部是相同的数,顺序天然是正确的升序,end处数不需要再移动结果也是正确的。

    所以快排序适用有重复元素的情况。

    快排序其他思路讲解:https://www.cnblogs.com/grandyang/p/5637862.html

     

    ——————————————————分割线————————————————

    在lintcode上遇到快排序时,我记得这个方法是选定一个基准,将比它小的放在它的左侧,比它大的放在它的右侧。然后在左侧区间与右侧区间重复这个过程,即递归。

    然而实现时,我只是将中间元素做基准,两根指针分别从头和尾开始遍历,头指针循环找到比基准大的,尾指针循环找到比基准小的,然后交换。重复这个过程直到头指针等于尾指针。

    然后递归左右区间。

    运行的时候结果不对。

    仔细思考了下,这个中间元素固定的话很有问题,你无法保证它的值一定是数组中间值。所以选定的基准也应该参与移动过程,找到它应该在的位置。

     

  • 相关阅读:
    服务器编程
    前端了解
    requests.post( )发送日志
    python---split函数
    Shell等待提示符"#"和"$"
    数据文件格式对读写速度的影响
    指针常量和常量指针的区别
    C++ 类构造函数 & 析构函数
    2016word多级列表 一级标题居中后偏左
    word交叉引用公式编号时和连公式一起引用
  • 原文地址:https://www.cnblogs.com/Tang-tangt/p/8847819.html
Copyright © 2020-2023  润新知