【C++】set、map、multiset、multimap的用法简介
RB-tree
是一种平衡二叉搜索树
,自动排序
效果很不错,所以标准的STL中set、map即以RB-tree作为底层的数据结构,set与map所开放的各种操作接口,RB-tree基本上都提供了,因此·set、map
都只是调用红黑树的方法对外层的一次封装
而已。
一、STL::set特性
1)set的元素的键值就是实值,实值就是键值,即仅有一个值。
2)set不允许出现两个元素拥有相同的键值。
3)set所有的元素的键值都会自动被排序(默认升序)。
4)set iterators是一种constant itertors(相对于mutable iterators)。
5)set使用红黑树作为底层的数据结构。
下面是set一些常用的接口,对于set的底层实现不多说明,感兴趣的可以去看源码:
#include <set>
#include <iostream>
using namespace std;
int main()
{
int arr[] = { 0,4,2,1,7,15,3,9,11 };//set会默认排序
set<int> _s(arr,arr+sizeof(arr)/sizeof(arr[0]));
cout << "Size: " << _s.size() << endl;//9
cout << "2 Count:" << _s.count(2) << endl;//1
_s.insert(2);//set不允许两个相同的键值
cout << "Size: " << _s.size() << endl;//9
cout << "Count:" << _s.count(2) << endl;//1
_s.erase(4);
cout << "Size: " << _s.size() << endl;//8
cout << "4 Count:" << _s.count(4) << endl;//0
set<int>::iterator it = _s.begin();//set的迭代器类型
while (it != _s.end())
{
cout << *it << " ";//set会自动排序
it++;
}
cout << endl;
//使用find可以有效搜寻元素,但不是个好方法
it = find(_s.begin(), _s.end(), 11);
if (it != _s.end())
cout << "found success." << endl;
else
cout << "find success" << endl;
//面对关联式容器,应该使用find函数来搜寻元素,会比
//STL的find更有效率,因为STL的find只是循序搜索
it = _s.find(15);
if (it == _s.end())
cout << "not found" << endl;
else
cout << "find success." << endl;
//*it = 10; //set是不能被修改的
int arr2[] = { 3,5,7,1,2,9,11,0 };
set<int> _s1(arr2, arr2 + sizeof(arr2) / sizeof(arr2[0]));
it = _s1.find(7);
_s1.erase(it,_s1.end());//删除it到end()之间的元素,默认会排序之后删除
it = _s1.begin();
while (it != _s1.end())
{
cout << *it << " ";//0 1 2 3 5
it++;
}
cout << endl;
system("pause");
return 0;
}
二、STL::map特性
1)map的所有元素都是pair,同时拥有键值key与实值value。
2)map不允许两个元素拥有相同的键值。
3)map的所有元素通过键值自动排序(默认升序)。
4)map的键值是不能被修改的,但是实值是可以被修改的。
5)map的使用红黑树作为底层的数据结构。
6)map重载了[],查询速度快。
下面是map一些常用的接口,对于set的底层实现不多说明,感兴趣的可以去看源码:
#include <map>
#include <iostream>
#include <string>
using namespace std;
int main()
{
map<string, int> _m;//以string为键值,以int为实值
_m[string("赵雷")] = 1;
_m[string("*")] = 2;
_m[string("宋冬野")] = 3;
pair<string, int> value(string("许巍"), 4);
_m.insert(value);
map<string, int>::iterator it = _m.begin();
while (it != _m.end())//map会根据键值默认排序
{
cout << it->first << " " << it->second << endl;
it++;
}
cout << _m[string("*")] << endl;//2
map<string, int>::iterator fd;
//我们尽量还有关联式容器提供的find(),效率较高
//STL提供的find()仅仅是循序搜索
fd = _m.find(string("许巍"));
if (fd == _m.end())
cout << "not find." << endl;
else
cout << "find success." << endl;
fd->second = 100;
cout << fd->first << " " << fd->second << endl;
//fd->first = "uuuuu";//不可以修改键值
cout << "Size: " << _m.size() << endl;//4
cout << _m.empty() << endl;
_m.clear();//清空map
cout << _m.empty()<< endl;
system("pause");
return 0;
}
三、STL::multiset特性
multiset的特性以及用法与set基本相同,两点差别在于:
1)multiset允许键值重复,它的插入动作调用的是insert_equal。
2)multiset的删除是删除所有值为key的元素。
#include <set>
using namespace std;
int main()
{
int arr[] = { 2,4,3,0,5,6,1 };
multiset<int> _ms(arr,arr + sizeof(arr) / sizeof(arr[0]));
cout << "Size:" << _ms.size() << endl;
multiset<int>::iterator it = _ms.begin();
while (it != _ms.end())
{
cout << *it << " ";//自动排序
++it;
}
cout << endl;
_ms.insert(2);//调用的是insert_equal,而不是insert_unique
cout << "Size:" << _ms.size() << endl;
it = _ms.begin();
while (it != _ms.end())
{
cout << *it << " ";//0 1 2 2 3 4 5 6
++it;
}
cout << endl;
_ms.erase(2);
it = _ms.begin();
while (it != _ms.end())
{
cout << *it << " ";//删除所有key为2的元素
++it;
}
cout << endl;
system("pause");
return 0;
}
STL::multimap特性
multimap的特性以及用法与map基本相同,差别如下:
1)允许重复键值的元素插入容器(使用了RB-Tree的insert_equal函数) 。
2)键值key与元素value的映射关系是多对多的关系。
3)没有重载[]操作运算。
4)删除key即删除键值为key的所有元素。
#include <iostream>
#include <map>
using namespace std;
int main()
{
std::multimap<char, int> mymultimap;
mymultimap.insert(pair<char, int>('a', 10));
mymultimap.insert(pair<char, int>('b', 20));
mymultimap.insert(pair<char, int>('b', 30));
mymultimap.insert(pair<char, int>('c', 40));
mymultimap.insert(pair<char, int>('d', 50));
mymultimap.insert(pair<char, int>('d', 60));
mymultimap.insert(pair<char, int>('e', 70));
mymultimap.insert(pair<char, int>('f', 80));
multimap<char, int>::iterator it;
for (it = mymultimap.begin(); it != mymultimap.end(); ++it)
cout << (*it).first << " " << (*it).second << endl;
mymultimap.erase('d'); //删除所有键值为d的元素
it = mymultimap.find('e');
mymultimap.erase(it, mymultimap.end()); //删除e到end()区间的所有元素
for (it = mymultimap.begin(); it != mymultimap.end(); ++it)
cout << (*it).first << " " << (*it).second << endl;
system("pause");
return 0;
}
参考博客:
https://blog.****.net/weixin_41413441/article/details/81603958