快速排序
理解快速排序
快速排序(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);
}