题目是408机试第一题
那题我写的记录上也记录了很多容易写错的地方
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
//忘记写这个了
const int N=1010;
typedef pair<string, int> PII;
//这里必须写成const的才能放到q[]里面去
PII q[N];
static bool cmp(PII a,PII b){
return a.second < b.second;
}
static bool re(PII a,PII b){
return a.second > b.second;
}
int n,m;
int main(){
cin>>n>>m;
for(int i=0;i<n;i++) cin>>q[i].first>>q[i].second;
if(m) stable_sort(q,q+n,cmp);
//自己打的时候发现stable_sort不会用,反正第三个参数从小到大不用写,从大到小就写greater<>(),其中泛型写那个结构体的类名
else stable_sort(q,q+n,re);
for(int i=0;i<n;i++) cout<<q[i].first<<" "<<q[i].second<<endl;
return 0;
}
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
//忘记写这个了
const int N=1010;
typedef pair<int, int> PII;
//这里必须写成const的才能放到q[]里面去
struct Person{
string name;
int num;
bool operator< (const Person& t) const{
return num<t.num;
}
bool operator> (const Person& t) const{
return num>t.num;
}
}q[N];
int n,m;
int main(){
cin>>n>>m;
for(int i=0;i<n;i++) cin>>q[i].name>>q[i].num;
if(m) stable_sort(q,q+n);
//自己打的时候发现stable_sort不会用,反正第三个参数从小到大不用写,从大到小就写greater<>(),其中泛型写那个结构体的类名
else stable_sort(q,q+n,greater<Person>());
for(int i=0;i<n;i++) cout<<q[i].name<<" "<<q[i].num<<endl;
return 0;
}
不同点
第一段代码
使用pair<string, int>:将姓名和数值封装为pair类型,这样可以直接利用pair的比较操作符重载,通过自定义的比较函数cmp和re来实现升序或降序排序。
自定义比较函数:定义了两个静态函数cmp和re作为排序准则,分别用于升序和降序排列。这种做法在需要更复杂比较逻辑时较为灵活。
第二段代码
使用结构体Person:定义了一个结构体Person来存储姓名和数值,相比pair,结构体可以提供更多灵活性,比如可以添加更多成员或方法。
重载比较运算符:在Person结构体内重载了<和>运算符,这使得可以直接使用默认的排序规则或者通过greater<Person>()来改变排序方向,代码看起来更加直观且结构清晰。
总结
第一种直接用pair作为自定义类型,装入数组,sort的逻辑写在cmp中,cmp要自己写
也就是说pair自定义类型和排序逻辑cmp是分开的
第二种自定义类型用的struct,然后在struct里面重载运算符,默认排序的时候不用加cmp,
反过来排序就用greater<struct名字>()
即可
注意重载运载符的使用规则
只需要升序排序,那么只需要定义<运算符。如果还需要降序排序,那么定义>运算符
是必要的。
ps:如果你选择了重载运算符的做法,但是又要反向排序,你会用到greater<struct>()
可能你会想这个东西不还是cmp吗,那重载运算符还有必要吗?
其实可以这么说,如果你只需要从小到大排序,你只用<
从大到小排序,你还的>并且搭配greater
–当然了,你就算只用<,也能实现从大到小的排序的逻辑
但是,我们这里谈的是同时实现从小到大,从大到小就借助greater
只实现一种当然随便实现了。–不行,事实证明,不那么写
编译器直接报错
gpt回答
是的,即使你只保留了带有greater<Person>()
的stable_sort调用:
stable_sort(q, q+n, greater<Person>());
你也仍然需要重载运算符。在这个场景中,虽然你没有直接使用自定义的<运算符,但greater<Person>()
比较器内部可能会用到它。greater是一个比较函数对象,它通常通过调用对象的<运算符来判断第二个对象是否大于第一个对象。因此,为了确保greater<Person>()
能正确工作,你的Person结构体中重载的>运算符是必要的。不过,严格来说,对于使用greater的情况,重载>运算符已经足够,因为greater实际上会转换为使用>逻辑来进行比较。
简而言之,如果你的代码中存在任何排序调用,并且这些调用依赖于对象之间的比较,那么相应的比较运算符(在这个案例中是<或>)就需要被重载以提供正确的比较逻辑。
这里额外再提一下,cmp不止用在sort这里,优先队列也有用
目前看来,优先队列的排序或者说是堆,排序只有cmp,没有重载运算符