前言:

如果我们有这样的需求:快速查找,统计,去重,映射存储等,我们就可以考虑选择使用set/multiset,map/multimap,接下来介绍其的接口及使用

文档:  《set》 ,《map》《multiset》《multimap》

一.set容器

set的底层由红黑树组成

接口说明:

1.构造函数

2.迭代器

end()指向的是最后一个元素的下一个

为了方便观察,我们实现一下打印函数

template<class Container>
void contain_print(const Container& con)
{
	auto it = con.begin();
	while (it != con.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

使用:

void test1()
{
	set<int> s1({6,2,8,3,9,1,5});//初始化列表构造
	contain_print(s1);
}

结果:

由此我们可以知道begin指向最小的元素

3.插入——insert

1.insert插入是按照平衡二叉树的插入规则插入的

2.set不插入相同值

3.单个元素插入的函数返回值是pair,pair的第一个类型是iterator(用于返回插入处的迭代器,如果有相同值,就返回相同值的迭代器),第二个类型是bool。

我们来看一下pair:

成员变量:

变量类型:可以互相不同

insert的使用:

void test2()
{
	set<int> s1({ 6,2,8 });
	pair<set<int>::iterator, bool>p1,p2;
	p1=s1.insert(7);
	cout << *(p1.first) << endl;
	p2=s1.insert(7);//再插入一个7
	cout << *(p2.first) << endl;//打印第一个插入的7
	if (p2.second)
	{
		cout << "插入成功" << endl;
	}
	else
	{
		cout << "插入失败" << endl;
	}
	
}

4.删除——erase

void test3()
{
	set<int> s1({ 6,2,8,3,9,7,1 });
	contain_print(s1);
	s1.erase(8);//指定元素删除
	contain_print(s1);
	auto it = s1.begin();
	for(int i=0;i<2;i++)
	{//指定迭代器位置删除
		it=s1.erase(it);//删除后,原位置迭代器失效,不能用++
	}
	contain_print(s1);
}

5.查找——find

void test4()
{
	set<int> s1({ 6,2,8,3,9,7,1 });
	cout << *(s1.find(6)) << endl;
}

6.统计节点个数——count

在set中,count只能为1或者0。在multiset中可以发挥真正功能

void test5()
{
	set<int> s1({ 6,2,8,3,9,7,1 });
	cout<< s1.count(6)<<endl;
	cout << s1.count(0) << endl;
	//用count统计multiset中的元素
	multiset<int> ms({ 4,3,6,4,4,6,7,4 });
	contain_print(ms);
	cout << ms.count(4) << endl;
}

7.区间查找——lower_bound/upper_bound

返回一个迭代器,该迭代器指向容器中第一个不被认为在 val 之前的元素(即该元素与 val 等价或在 val 之后)。

指向相同元素或较小于这个值的下一个

void test6()
{
	//(0,10)
	set<int> s1({ 6,2,8,3,9,7,1 });
	auto begin=s1.lower_bound(0);//begin指向1
	auto end = s1.upper_bound(10);//指向末尾
	while (begin != end)
	{
		cout << *begin << " ";
		begin++;
	}
}

二.multiset容器

multiset和set只是略有不同,接口功能相似,multiset不同在于insert可以插入相同值,由此其它接口也会略有区别。

1.insert

void test7()
{
	multiset<int> ms;
	ms.insert(1);
	ms.insert(1);
	ms.insert(1);
	ms.insert(1);
	contain_print(ms);
}

2.erase

erase会删除所有相同的元素

void test8()
{
	multiset<int> ms;
	ms.insert(1);
	ms.insert(1);
	ms.insert(1);
	ms.insert(1);
	contain_print(ms);
	ms.erase(1);
	cout << "删除完毕" << endl;
	contain_print(ms);

}

3.查找——find

当有重复元素的时候,返回第一个元素的迭代器

void test9()
{
	multiset<int> ms({5,7,3,5,8,2,2,7,1,7});
	contain_print(ms);
	auto it=ms.find(7);
	while (it != ms.end())
	{
		cout << *it << " ";
		it++;
	}
}

4.统计元素个数——count

void test10()
{
	multiset<int> ms({ 5,7,3,5,8,2,2,7,1,7 });
	contain_print(ms);
	cout << ms.count(7) << " ";
}

5.返回迭代器区间——equal_range

返回一个范围的边界,该范围包含容器中所有与 val 等效的元素。

void test12()
{
	multiset<int> ms({ 5,7,3,5,8,2,2,7,1,7 });
	contain_print(ms);
	pair<multiset<int>::iterator, multiset<int>::iterator> p1;
	p1 = ms.equal_range(7);
	auto it = p1.first;
	while (it != p1.second)
	{
		cout << *it << " ";
		it++;
	}

}

由此可知second是最后一个相同元素的下一个

三.map容器

map接口与set差别不大,因为map的元素是类似pair<key,value>类型的,用来判别的元素为key,只是映射值value所以略有不同。

1.构造函数

void test1()
{
	map<int, string> m1{ {1,"张三"},{2,"李四"},{7,"苹果"},{9,"没有"}};//初始化列表构造
	map<int, string> m2(m1);//拷贝构造
	map_print_container(m1);
	map_print_container(m2);
	auto it = m1.begin();
	it++;
	map<int, string> m3(it,m1.end());//迭代器区间构造
	map_print_container(m3);

}

2.插入——insert

我们可以构造pair作为单个元素进行插入

void test2()
{
	map<int, string> m1{ {1,"张三"},{2,"李四"},{7,"苹果"},{9,"没有"} };
	pair<int, string> p1(4, "二维");
	m1.insert(p1);//单个元素插入
	map_print_container(m1);
	map<int, string> m2;
	m2.insert({5,"大赛"});//隐式类型转换
	map_print_container(m2);
	map<int, string> m3;
	auto it = m1.begin();
	it++;
	m3.insert(it, m1.end());//迭代器区间插入
	map_print_container(m3);
}

还有一个问题:遇到与插入元素的key值相同但是second值不同,insert会不会进行更新?

void test3()
{
	map<int, string> m1{ {1,"张三"},{2,"李四"},{7,"苹果"},{9,"没有"} };
	pair<int, string> p1(1, "二维");
	auto it= m1.insert(p1);
	cout << it.first->first << ":" << it.first->second << " ";

}

结果是不会。

3.operator[ ]

operator返回值为映射值

功能:加上“ = ”可以插入数据,如果元素不存在,就会插入;如果数据存在,就会修改其映射值

void test4()
{
	map<int, string> m1{ {1,"张三"},{2,"李四"},{7,"苹果"},{9,"没有"} };
	m1[1] = "二维";
	map_print_container(m1);

}

由此,我们可以把map当计数器来用

void test5()
{
	
	vector<string>v{ "苹果","苹果","苹果","香蕉","离子","电子","香蕉","苹果","香蕉","电子","苹果","电子" };
	map<string, int>count;
	auto it = v.begin();
	while (it != v.end())
	{
		count[*it]++;
		it++;
	}
	map_print_container(count);


}

四.multimap容器

与map几乎一样,只是支持相同元素

例如:
1.erase

void test6()
{
	multimap<int, string>mu{ {1,"张三"},{2,"李四"},{7,"苹果"},{9,"没有"},{1,"历史"}};
	map_print_container(mu);
	mu.erase(1);
	map_print_container(mu);
}

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐