STL有序容器:set/multiset和map/multimap的使用介绍
前言:
如果我们有这样的需求:快速查找,统计,去重,映射存储等,我们就可以考虑选择使用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);
}

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

所有评论(0)