About 二元排序
谈 C++ 之二元排序
二元排序的定义
本人自己瞎编的名称。
我们在切水题时,通常会遇到这样的问题。
给定两个长度为 \(n\) 的序列 \(a_1,a_2,a_3 \cdots a_n\) 和 \(b_1,b_2,b_3 \cdots b_n\)。
先按 \(a\) 从小到大排序,再按 \(b\) 从小到大排序。
数组实现
这是最常见且最普通的方式,相信大家都会,这里就直接贴代码惹。
外置比较函数
struct node{
int a,b;
}s[N];
bool cmp(node a,node b){
if(a.a==b.a) return a.b<b.b;
return a.a<b.a;
}
for(int i=1;i<=n;i++)
cin>>s[i].a>>s[i].b;
sort(s+1,s+1+n,cmp);
外置重置运算符函数
struct node{
int a,b;
}s[N];
bool operator < (node a,node b){
if(a.a==b.a) return a.b<b.b;
return a.a<b.a;
}
for(int i=1;i<=n;i++)
cin>>s[i].a>>s[i].b;
sort(s+1,s+1+n);
内置重置运算符函数
struct node{
int a,b;
//以下两种二选一。
friend bool operator < (node x,node y){//运用 friend,与 cmp 函数差不多。
if(x.a==y.a) return x.b<y.b;
return x.a<y.a;
}
bool operator < (const node& p) const{//传统写法。
if(a==p.a) return b<p.b;
return a<p.a;
}
}s[N];
for(int i=1;i<=n;i++)
cin>>s[i].a>>s[i].b;
sort(s+1,s+1+n);
pair 数组实现
pair 默认先按 \(first\) 从小到大排序,再按 \(second\) 从小到大排序。
pair<int,int> s[N];
for(int i=1;i<=n;i++)
cin>>s[i].first>>s[i].second;
sort(s+1,s+1+n);
vector 实现
vector 是一种很棒的容器,可实现动态的空间管理。空间一般比数组小得多。
pair 实现
vector<pair<int,int> > s;
for(int i=1;i<=n;i++){
int a,b;
cin>>a>>b;
s.push_back(make_pair(a,b));
}
sort(s.begin(),s.end());
//以下三种输出是等价的。
for(auto it:s)
cout<<it.first<<' '<<it.second<<'\n';
for(vector<pair<int,int> >::iterator it=s.begin();it!=s.end();it++)
cout<<it->first<<' '<<it->second<<'\n';
for(int i=0;i<s.size();i++)
cout<<s[i].first<<' '<<s[i].second<<'\n';
结构体实现
struct node{
int a,b;
bool operator < (const node& p) const{
if(a==p.a) return b<p.b;
return a<p.a;
}
node(int aa,int bb):a(aa),b(bb){}
};
vector<node> s;
for(int i=1;i<=n;i++){
int a,b;
cin>>a>>b;
s.push_back(node(a,b));
// s.push_back({a,b});//同上。
}
sort(s.begin(),s.end());
//以下三种输出是等价的。
for(auto it:s)
cout<<it.a<<' '<<it.b<<'\n';
for(vector<node>::iterator it=s.begin();it!=s.end();it++)
cout<<it->a<<' '<<it->b<<'\n';
for(int i=0;i<s.size();i++)
cout<<s[i].a<<' '<<s[i].b<<'\n';
priority_queue 优先队列(堆)实现
priority_queue 以堆的形式储存,复杂度相同,但是是一次性的。
pair 实现
priority_queue<pair<int,int> > s;
for(int i=1;i<=n;i++){
int a,b;
cin>>a>>b;
s.push(make_pair(a,b));
}
while(!q.empty()){
cout<<q.top().first<<' '<<q.top().second<<'\n';
q.pop();
}
结构体实现
struct node{
int a,b;
bool operator < (const node& p) const{
if(a==p.a) return b<p.b;
return a<p.a;
}
node(int aa,int bb):a(aa),b(bb){}
};
priority_queue<node> s;
for(int i=1;i<=n;i++){
int a,b;
cin>>a>>b;
s.push(node(a,b));
// s.push({a,b})//同上。
}
while(!q.empty()){
cout<<q.top().a<<' '<<q.top().b<<'\n';
q.pop();
}
set/multiset 红黑树实现
set 以红黑树的形式储存,复杂度相同,且自动去重。
如不想去重,可使用 multiset
pair 实现
set<pair<int,int> > s;
for(int i=1;i<=n;i++){
int a,b;
cin>>a>>b;
s.insert(make_pair(a,b));
}
for(set<pair<int,int> >::iterator it=s.begin();it!=s.end();it++)//注意:这里的 ++ 复杂度是 O(log n) 的。
cout<<it->first<<' '<<it->second<<'\n';
结构体实现
struct node{
int a,b;
bool operator < (const node& p) const{
if(a==p.a) return b<p.b;
return a<p.a;
}
node(int aa,int bb):a(aa),b(bb){}
};
set<node> s;
for(int i=1;i<=n;i++){
int a,b;
cin>>a>>b;
s.insert(node(a,b));
// s.insert({a,b});//同上。
}
for(set<node>::iterator it=s.begin();it!=s.end();it++)//注意:这里的 ++ 复杂度是 O(log n) 的。
cout<<it->a<<' '<<it->a<<'\n';
总结
以上方式时间复杂度均为 \(O(n \log n)\),且代码简洁,主要是字太多懒得打。但各有优缺点。
这篇博客主要是给一些看不懂 DALAO 写的 TJ 的小盆友,DALAO请自动跳过。

浙公网安备 33010602011771号