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请自动跳过。

完结撒花

posted @ 2026-01-29 21:32  concert_b  阅读(1)  评论(0)    收藏  举报