sort()简介
sort() 是 C++ 标准库中的一个排序函数,定义在
a
l
g
o
r
i
t
h
m
algorithm
algorithm 头文件中。
它的排序时间复杂度是
O
(
n
l
g
n
)
O(nlgn)
O(nlgn),远胜于普通的冒泡排序和选择排序。
现在介绍其函数重载、使用方法以及快速排序的具体实现。
sort()使用方法
默认排序(不传入函数参数)
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main(){
vector<int> example={11,42,3,24};
sort(example.begin(),example.end());//传入迭代器或指针,指向开头和结尾,默认是升序排序
int example1[]={22,33,11};
sort(example1,example1+3);//注意,若手动管理地址,则要求左闭右开,与迭代器同
}
传入函数参数
可以调用C++的预定义比较器,储存在 f u n c t i o n a l functional functional头文件中
std::greater<T>//降序排序,把T换成需要比较的类型
std::less<T>//升序排序,默认,可省略
传入参数格式示例
#include<iostream>
#include<algorithm>
#include<vector>
#include<functional>
using namespace std;
int main(){
vector<int> example={11,42,3,24};
sort(example.begin(),example.end());//传入迭代器或指针,指向开头和结尾,默认是升序排序
int example1[]={22,33,11};
sort(example1,example1+3,greater<int>());//注意,若手动管理地址,则要求左闭右开,与迭代器同
for(auto& a:example){
cout<<" "<<a;
}
cout<<endl;
for(auto& a:example1){
cout<<" "<<a;
}
return 0;
}
输出结果:
3 11 24 42
33 22 11
自定义比较函数写法:
#include<iostream>
#include<algorithm>
#include<vector>
#include<functional>
using namespace std;
bool cmp(int a, int b) {
return a>b;//返回值为真,则传入顺序为真,即a在前,b在后,此为降序排序
}
int main(){
vector<int> example={11,42,3,24};
sort(example.begin(),example.end());//传入迭代器或指针,指向开头和结尾,默认是升序排序
int example1[]={22,33,11};
sort(example1,example1+3,cmp);//自定义函数不需要括号,只需要传入函数名
for(auto& a:example){
cout<<" "<<a;
}
cout<<endl;
for(auto& a:example1){
cout<<" "<<a;
}
return 0;
}
输出结果:
3 11 24 42
33 22 11
记忆技巧:若返回值为真,则代表a在前面,b在后面
故想要升序排序则返回a>b,想要降序排序则返回a<b
快速排序实现
快排的原理就是二分化处理数组,以实现遍历logn次就能使数组有序。
(一般地,在时间复杂度领域提到log都是指以2为底)
下面提供一个快排的升序实现代码
#include<iostream>
#include<utility>
using namespace std;
inline
void mysort(int* arr,int left,int right){//闭区间
if(left==right)
return;
int middle=(left+right)/2;
int flag=arr[middle];
int cut=0;
for(int l=left,r=right;;l++,r--){
while(arr[l]<flag)//尽量创造条件丢过去,不取等,否则当flag为最大值时,会因为cut=right而出错
l++;
while(arr[r]>flag)
r--;
if(l<r)
swap(arr[r],arr[l]);
else{
cut=r;
break;
}
}
//当循环break后,知道r的右边都是大于flag的数字,l同理
//把cut判给左边
mysort(arr,left,cut);
mysort(arr,cut+1,right);
return;
}
int main(){
int example1[]={1,42,3,24,5,74,29,58,22,33,11};
mysort(example1,0,10);
for(auto& a:example1){
cout<<" "<<a;
}
return 0;
}
输出结果: 1 3 5 11 22 24 29 33 42 58 74
快排实现时,要主要好边界条件以及比较条件。
比较flag数时,取等会发生什么情况呢
考虑极端情况下,若flag数为最大值,那么r就会停留在右边(r去找小于flag的数字),l也会到最右边
如此一来,cut+1就越界了。
然而,理论上,flag取数组中数字时,完全可以保证起码r右边有一个数字
因此,就发现必须让flag参与交换之中,才能保证当flag为最值时不越界。
当flag不为最值时,显然r右侧必定有一个数,不会越界
若cut取l左侧,思考过程类似,不再赘述。