L2-039 清点代码库 (25 分)

这篇博客详细介绍了C++ STL中set和vector的使用,特别是set的自排序特性和如何自定义排序规则。通过定义cmp结构体重载比较操作符,可以改变set中元素的排序方式。同时,文章提到了vector可以直接进行比较,并展示了如何利用map统计vector出现的次数,然后用结构体存储并排序。更新后的代码简化了这一过程,直接利用vector的比较功能进行排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

题目链接

题解

考查STL。


set 容器排序详讲

set内部本身自带排序函数,也就是说插入set后通过迭代器或者auto输出的结果都是升序排列的;如果想要改变排序方式,可以自己定义一个cmp结构体,重载set<?>?()操作符,比如:

#define PSI pair<string, int>
struct cmp {
	bool operator() (const PSI & a, const PSI & b) const {
		if (a.second != b.second) return a.second > b.second;
		return a.first < b.first;
	}
};
set<PSI, cmp> s;

vector自带比较函数,可以直接比较v1与v2,从头开始按顺序比较,v1[i]>v2[i]说明v1>v2。


更新于2022.4.22

发现其实根本不用这么麻烦,只要知道vector是可以自己比较大小是就行了。

用map统计出每种vector的数量;
用个结构体保存,索引就是正常编号,数据项为vector和vector的个数;
再重新遍历输入的每一行,如果遍历过了这个vector,那么就continue,没遍历过就相当于遇到了一个独一无二的vector,结构体编号加一,vector赋值为遍历到的,个数赋值为上面map统计的数量;
遍历完成,sort,重写cmp;
输出。

代码

#include<bits/stdc++.h>
#define VI vector<int>,int
#define PVI pair<VI>
using namespace std;
int n, m, x;
vector <int> v;

struct cmp { // !!! 
	bool operator() (const PVI & a, const PVI & b)  {
		if (a.second != b.second) return a.second > b.second;
		return a.first < b.first; // vector自带比较大小的函数 
	}
};

map <VI> Map;
set <PVI, cmp> s; // !!!

int main()
{
	cin >> n >> m;
	for (int i = 1;i <= n;i ++) {
		v.clear ();
		for (int j = 1;j <= m;j ++)
			cin >> x, v.push_back (x);
		Map[v] ++;
	}	
	
	for (auto item : Map) {
		v = item.first;
		int cnt = item.second;
		s.insert ({v, cnt});
	}
	
	cout << s.size () << endl;
	for (auto item : s) {
		v = item.first;
		int cnt = item.second;
		cout << cnt << ' ' << v[0];
		for (int i = 1;i < v.size();i ++)
			cout << ' ' << v[i];
		cout << endl;
	}

	return 0;
}

更新后的代码

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;

int n, m, num;
map <vector <int>, int> st, cnt;
vector <int> v[N];

struct Node {
	int cnt;
	vector <int> v;
} node[N];

bool cmp (Node a, Node b) {
	if (a.cnt != b.cnt) return a.cnt > b.cnt;
	return a.v < b.v;
}

int main()
{
	cin >> n >> m;
	for (int i = 0;i < n;i ++) {
		for (int j = 0;j < m;j ++) {
			int x;
			cin >> x;
			v[i].push_back (x);
		}
		cnt[v[i]] ++;
	}
	for (int i = 0;i < n;i ++) {
		if (st[v[i]]) continue;
		st[v[i]] = 1;
		node[num].cnt = cnt[v[i]];
		node[num].v = v[i];
		num ++;
	}
	sort (node, node+num, cmp);
	cout << num << endl;
	for (int i = 0;i < num;i ++) {
		cout << node[i].cnt;
		for (int j = 0;j < node[i].v.size();j ++)
			cout << ' ' << node[i].v[j];
		cout << endl;
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不牌不改

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值