排序:“快速排序” 就应该这样快速理解

理解快速排序

快速排序(Quicksort)是对冒泡排序的一种改进。

快速排序是由 C.A.R.Hoare 在1960年提出。它的基本思想是:
      通过一趟排序将要排序的数据分割成独立的两部分,一部分的所有数据都比另外一部分的所有数据都要小,然后再按照该方法对这两部分分别进行快速排序,整个过程使用递归进行,以此达成有序序列。


我们呢,需要注意关键点: 重复划分大区和小区

快速排序的思路呢,我们简单模拟理解一下:

arr: 2 5 1 4 9
选择一个划分大小区的中间标志位值:4
划分后的arr:2 1 4 5 9  大区为:5 9  小区为:2 1
对大区进行选择标志位并划分大小区:5 9 标志位为 5          小区为: null   大区为: 9
对大区进行选择标志位并划分大小区:1 2 标志位为 2          小区为: 1      大区为:null
直到各区再次划分时 区域元素个数小于 2 为止结束。
不断划分区域后的最终 arr:1 2 4 5 9

下面附带上快速排序的理解图:
在这里插入图片描述

实现 重复划分大小区的操作是最关键的 :
这里我介绍一下我们的思路:我们对要求的序列实现大小区后,返回其中间的标志位的角标值,之后再次递归对角标前的 小区 和角标后的 大区 进行划分大小区,这样不断划分区域到元素数量小于2 时结束该划分过程,最终递归结束,我们的快速排序就实现了。

函数名称及参数列表详情:

using sz=vector<int>::size_type ;
int myParition(vector<int>& ivec,sz start,sz end){ 
}

我们快速理解一下划分大小区的实现思路:

标志位我们取 未排序序列的最后一个元素值。

双角标法:left 指向序列开始位置,right 指向序列最后位置
角标变化规则:left指向的元素呢,一直递增到大于标志位的元素位置,紧接着right指向的元素一直递减
到小于标志位的元素位置,之后元素交换。
结束条件:left 指向与 right 指向相同。
最后的步骤:交换 left 与 right 同时指向的元素与标志位元素,因为 left 与 right同时指向的元素一定是大于等于 标志位的,所以将其交换即可得到标志位的最终位置,并返回该位置值。
注意点:left 指向位置应始终小于 right 指向位置。

using sz=vector<int>::size_type ;
int myParition(vector<int>& ivec,sz start,sz end){   //分治函数,比基点大的元素均在右边,小的在左边
        if(end>=ivec.size()){
            cerr<<"Invalid parameters!"<<endl;
            throw new exception();
        }
        int &keyVal = ivec.at(end);        //引用标志位
        while(start < end){
           //递推 start直到大于标志位的值出现
            while (start < end && ivec.at(start)<= keyVal)  ++start;  
           //递减end直到小于标志位的值出现
            while (start < end && ivec.at(end) >= keyVal)   --end;     
            if(start!=end)
                swap(ivec.at(start),ivec.at(end));
        }
        swap(keyVal,ivec.at(start)); //将标志位移动到分区点位置
        return start;
}



来,快速的上手代码吧

测试用例:

  • 功能测试:{9,3,4,5,6,2,1}
  • 边界值测试:{1},{2,1}
  • 重复值测试:{1,1,2,3,1,3,1,9,9,7,6,6}
  • 性能测试:{输入上千上万测试用例,进行压力测试}
using sz=vector<int>::size_type ;
int myParition(vector<int>& ivec,sz start,sz end){   //分治函数,比基点大的元素均在右边,小的在左边
        if(end>=ivec.size()){
            cerr<<"Invalid parameters!"<<endl;
            throw new exception();
        }
        int &keyVal = ivec.at(end);
        while(start < end){
            while (start < end && ivec.at(start)<= keyVal)  ++start;
            while (start < end && ivec.at(end) >= keyVal)   --end;
            if(start!=end)
                swap(ivec.at(start),ivec.at(end));
        }
        swap(keyVal,ivec.at(start));
        return start;
}
/*
 * end 为最后一个元素角标
 */
void myQuickSort(vector<int>& ivec,sz start,sz end){  //快速排序
    if(ivec.size()<2 || start>=end) return;   //考虑好输入的错误问题
    int index = myParition(ivec,start,end);
    if(start<index)
        myQuickSort(ivec,start,index-1);
    if(end > index)
        myQuickSort(ivec,index+1,end);
}
发布了42 篇原创文章 · 获赞 25 · 访问量 3243

猜你喜欢

转载自blog.csdn.net/chongzi_daima/article/details/105091026