C++ set用法总结
程序员文章站
2022-03-23 13:28:06
...
最近对set的使用频繁掉坑,所以做一个总结
一、set的erase()
set的erase()可删除单个元素也可删除一个区间的元素
例如:
`set<int>s;
for(int i=0;i<10;i++)s.insert(i);
s.erase(s.find(1));
s.erase(s.begin(),s.end());
二、set中结构体自定义去重和排序函数
1.详解
set和map的内部实现都是红黑树,默认排序都是从小到大。但是有时用到的元素是结构体而不是基本类型,就需要自定义排序,不然就会报错。自定义排序就需要重载<。再提一点priority_queue是默认优先级大的排前面,所以默认排序是从大到小。
详解传送门
这里有大佬讲得很详细。总结一点set的去重,在重载operator<时,让相同的两个对象总是返回false。(因为set是通过交换两个元素的左右位置,根据返回的值判断两个元素是否相同)
2.自定义的注意事项
但是很有意思的一件事情是,我在做csp推荐系统这道题时,定义了如下结构体:
我的本意是,不管score的值如何,只要type和id相同则判断是同一个元素
struct node
{
int type;
int id;
int score;
friend bool operator<(node n1, node n2)
{
if (n1.type == n2.type&&n1.id == n2.id)//type,id均相同则判断为同一元素
{
return false;
}
if (n1.score != n2.score)
{
return n1.score >n2.score;
}
else if (n1.type != n2.type)
{
return n1.type < n2.type;
}
else
{
return n1.id< n2.id;
}
}
};
在后面的代码中有对set中元素的删除操作,我的目的是根据type和id查找到某一元素,并将其删除(没有对score进行处理)。神奇的事情发生了,这样操作在devc下可以将对应type和id值相同的元素删除,但是在vs下却不可以。并且我在csp的oj系统上提交该代码,爆零。
int type, id;
scanf("%d%d", &type, &id);
node temp;
temp.type = type;
temp.id = id;
set<node>::iterator it = products.find(temp);
if (it != products.end())products.erase(it);
完整代码如下
#include<iostream>
#include<vector>
#include<set>
#pragma warning (disable:4996)
using namespace std;
int k[100], procount[100];
int m, n, K;
vector<int> query[100];
struct node
{
int type;
int id;
int score;
friend bool operator<(node n1, node n2)
{
if (n1.type == n2.type&&n1.id == n2.id)//type,id均相同则判断为同一元素
{
return false;
}
if (n1.score != n2.score)
{
return n1.score >n2.score;
}
else if (n1.type != n2.type)
{
return n1.type < n2.type;
}
else
{
return n1.id< n2.id;
}
}
};
//vector<node> goods;
set<node> products;
int main()
{
scanf("%d%d", &m, &n);
for (int i = 0; i < n; i++)
{
int id, score;
scanf("%d%d", &id, &score);
for (int j = 0; j < m; j++)
{
//goods.push_back(node{j,id,score});
products.insert(node{ j,id,score });
}
}
int opnum;
scanf("%d", &opnum);
for (int i = 0; i < opnum; i++)
{
//char str[2];
//getchar();
int op;
scanf("%d", &op);
if (op == 1)
{
int type, id, score;
scanf("%d%d%d", &type, &id, &score);
products.insert(node{ type,id,score });
}
if (op == 2)
{
int type, id;
scanf("%d%d", &type, &id);
node temp;
temp.type = type;
temp.id = id;
set<node>::iterator it = products.find(temp);
if (it != products.end())products.erase(it);
}
if (op == 3)
{
scanf("%d", &K);
for (int j = 0; j < m; j++)
{
scanf("%d", &k[j]);
}
int totcount = 0;
for (set<node>::iterator iit = products.begin(); iit != products.end(); iit++)
{
node pro = *iit;
int u = pro.type;
if (procount[u] < k[u])
{
procount[u]++;
totcount++;
query[u].push_back(pro.id);
if (totcount == K)break;
}
}
for (int mm = 0; mm < m; mm++)
{
if (query[mm].size() != 0)
{
for (int ii = 0; ii < query[mm].size(); ii++)
{
printf("%d ", query[mm][ii]);
}
}
else
{
printf("-1");
}
query[mm].clear();
printf("\n");
}
fill(procount, procount + 100, 0);
}
}
system("pause");
return 0;
}
之后我用另一个set单独存储了删除元素,代码就AC了
代码如下:
#include<iostream>
#include<vector>
#include<set>
#pragma warning (disable:4996)
using namespace std;
int k[100], procount[100];
int m, n, K;
vector<int> query[100];
struct node
{
int type;
int id;
int score;
friend bool operator<(node n1, node n2)
{
if (n1.type == n2.type&&n1.id == n2.id)
{
return false;
}
if (n1.score != n2.score)
{
return n1.score >n2.score;
}
else if (n1.type != n2.type)
{
return n1.type < n2.type;
}
else
{
return n1.id< n2.id;
}
}
};
struct delNode
{
int type;
int id;
friend bool operator<(delNode n1, delNode n2)
{
if (n1.type != n2.type)
{
return n1.type < n2.type;
}
else
{
return n1.id< n2.id;
}
}
};
//vector<node> goods;
set<node> products;
set<delNode> delSet;
int main()
{
scanf("%d%d", &m, &n);
for (int i = 0; i < n; i++)
{
int id, score;
scanf("%d%d", &id, &score);
for (int j = 0; j < m; j++)
{
//goods.push_back(node{j,id,score});
products.insert(node{ j,id,score });
}
}
int opnum;
scanf("%d", &opnum);
for (int i = 0; i < opnum; i++)
{
//char str[2];
//getchar();
int op;
scanf("%d", &op);
if (op == 1)
{
int type, id, score;
scanf("%d%d%d", &type, &id, &score);
products.insert(node{ type,id,score });
}
if (op == 2)
{
int type, id;
scanf("%d%d", &type, &id);
//qnode temp;
/* temp.type = type;
temp.id = id;
set<node>::iterator it = products.find(temp);
if (it != products.end())products.erase(it);
*/
delSet.insert(delNode{type,id});
}
if (op == 3)
{
scanf("%d", &K);
for (int j = 0; j < m; j++)
{
scanf("%d", &k[j]);
}
int totcount = 0;
for (set<node>::iterator iit = products.begin(); iit != products.end(); iit++)
{
node pro = *iit;
int u = pro.type;
set<delNode>::iterator ii=delSet.find(delNode{pro.type,pro.id});
if(ii!=delSet.end())continue;//注意是不等于的时候continue
if (procount[u] < k[u])
{
procount[u]++;
totcount++;
query[u].push_back(pro.id);
if (totcount == K)break;
}
}
for (int mm = 0; mm < m; mm++)
{
if (query[mm].size() != 0)
{
for (int ii = 0; ii < query[mm].size(); ii++)
{
printf("%d ", query[mm][ii]);
}
}
else
{
printf("-1");
}
query[mm].clear();
printf("\n");
}
fill(procount, procount + 100, 0);
}
}
// system("pause");
return 0;
}
上一篇: C++ set用法总结
下一篇: python的骚操作