更具体的看【速记】C++ STL自定义排序 - 知乎 (zhihu.com)
sort
sort第三个位置放的greater<int>和less<int>萌新可能会弄错,这两个单词不是更大和更小的意思,而是大于和小于,并且比较就是自定义排序中的前者和后者。
如果是less,就代表 前者小于后者,那么自然是升序。
vector<int>a;
a.push_back(3);
a.push_back(2);
sort(a.begin(),a.end(),less<int>());
for(auto i:a)cout<<i<<" ";
同理的,greater的意思就是 前者大于后者 自然就是降序,代码就不再展示了。
默认写法,就是使用less和greater,但是有时候默认排序可能不满足我们的要求,就要自定义了,下面记录一下都可以的。
1、使用cmp函数,cmp里面的a,b含义就是容器的前者和后者,因此这么写也是升序。
bool cmp(int a,int b){
return a<b;
}
void solve(){
vector<int>a;
a.push_back(3);
a.push_back(2);
sort(a.begin(),a.end(),cmp);
for(auto i:a)cout<<i<<" ";
}
当然你想容器里面套更多的元素也是可以的。
bool cmp(array<int,2> a,array<int,2> b){
return a[0]>b[0];
}
void solve(){
vector<array<int,2>>a;
a.push_back({1,2});
a.push_back({2,3});
sort(a.begin(),a.end(),cmp);
for(auto i:a)cout<<i[0]<<" "<<i[1]<<endl;
}
2、写法Lambda函数,本质上还是在用函数,不过把函数写成Lambda形式了。
vector<int>a;
a.push_back(3);
a.push_back(2);
auto cmp=[&](int a,int b){
return a<b;
};
sort(a.begin(),a.end(),cmp);
for(auto i:a)cout<<i<<" ";
或者使用Lambda形式的匿名表达式
vector<int>a;
a.push_back(3);
a.push_back(2);
sort(a.begin(),a.end(),[](int a,int b){
return a<b;
});
for(auto i:a)cout<<i<<" ";
tip:改成int &a,int &b,不会更快,因为sort函数不会产生新数组,是在原有的数组上排序,观察sort可以发现,第一个是 首地址,第二个是 结束地址。
当然也可以使用function来封装函数。
vector<int>a;
a.push_back(3);
a.push_back(2);
function<bool(int a,int b)>cmp=[&](int a,int b){
return a<b;
};
sort(a.begin(),a.end(),cmp);
for(auto i:a)cout<<i<<" ";
3、重载运算符(个人感觉写个cmp函数更方便)
struct Node{
int val;
bool operator < (const Node &b){
return val>b.val;
}
}a[3];
void solve(){
a[1].val=2;
a[2].val=3;
sort(a+1,a+2+1);
cout<<a[1].val<<" "<<a[2].val;
}
因为默认是 less 排序,即升序,所以我们要重载小于号。
比如这里改成 前者大于后者(这里val就是前者,右边的那个常量就是后者)
输出就是
会自动排序的容器
类似set,map这种容器,我们就不能用sort了,要提前定好一个排序类,重载内部的排序。
比较方式不变,依旧是前者和后者的比较。
tip:优先队列排序,输出最后面的(如less升序,就输出最大值。greater降序,就输出最小值),如果要 重载优先队列,这一点要多注意。
理论上map和set只有 key是自动排序的,value不会,所以不建议对value自定义排序。
比如下面要对map重载成自动降序。
struct MyMap{
bool operator() (const int &a,const int &b)const{
return a>b;
}
};
map<int,int,MyMap>f;
void solve(){
f[1]=2;
f[2]=1;
for(auto i:f)cout<<i.fr<<" ";
}
显然这是没必要的。
因为map可以逆序遍历。
正序是 begin()->end()
逆序就是 rbegin()->rend()
r就是单词reverse(反向、逆向都行)的缩写。
重载自动排序的类,里面格式都是固定的,比如 bool operator() (const &,consg &)const{}
下面再放一个对自定义类自动排序的。
struct Node{
int a,b;
};
struct MyMap{
bool operator() (const Node &A,const Node &B)const{
return A.a<B.a;
}
};
map<Node,bool,MyMap>f;
void solve(){
f[{2,1}]=1;
f[{1,2}]=1;
for(auto i:f){
cout<<i.fr.a<<" "<<i.fr.b<<endl;
}
}