欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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;
}