大小容量
- size() 求set元素个数
- empty() 判断set是否为空
插入
pair<iterator,bool> insert (const value_type& val);
返回值pair<iterator,bool>插入数据的位置以及插入是否成功的数据
void test()
{
vector<int> vec = { 4, 3, 9, 6, 3 };
set<int> set2 = { vec.begin(), vec.end() };//通过迭代器创建set容器
//ret.second表示pair对象第二个数据,ret.first表示pair对象第一个数据
pair<set<int>::iterator, bool> ret = set2.insert(7);
cout << ret.second << " " << \*ret.first << endl;//插入成功,pair第一个数据是新数据的迭代器
ret = set2.insert(7);
cout << ret.second << " " << \*ret.first << endl;//插入失败,pair第一个数据是已经存在的数据的迭代器
}
测试:
iterator insert (iterator position, const value_type& val);
该接口并非是说在该迭代器的位置前插入数据,其实和上一个插入是一样的
void printSet(const set<int>& set)
{
for (auto& s : set)
cout << s << " ";
cout << endl;
}
void test()
{
vector<int> vec = { 4, 3, 9, 6, 3 };
set<int> set2 = { vec.begin(), vec.end() };
printSet(set2);
auto it = set2.end();
set2.insert(it, 1);
printSet(set2);
}
测试:
删除
size_type erase (const value_type& val);
返回值是删除的个数,存在则删除并返回1,不存在返回0
void erase (iterator position);
void erase (iterator first, iterator last);
void test()
{
vector<int> vec = { 4, 3, 9, 6, 3, 10, 12, 50, 1 };
set<int> set2 = { vec.begin(), vec.end() };
set<int> ::iterator it = set2.begin();
int ret = set2.erase(6);//删除成功返回1
printSet(set2);
cout << ret << endl;
ret = set2.erase(5);//删除失败返回0
printSet(set2);
cout << ret << endl;
set2.erase(it);//注意不能传非法位置:end()
printSet(set2);
set2.erase(++set2.begin(), --set2.end());//删除只剩头和尾两个数据
printSet(set2);
}
测试:
查找
iterator find (const value_type& val) const;
找到返回数据的迭代器,找不到返回set容器的end()迭代器
void test()
{
vector<int> vec = { 4, 3, 9, 6, 3, 10, 12, 50, 1 };
set<int> set2 = { vec.begin(), vec.end() };
set<int> ::iterator it = set2.begin();
auto it = set2.find(3);
cout << (it != set2.end()) << endl;
auto it = set2.find(2);
cout << (it != set2.end()) << endl;
}
测试:
size_type count (const value_type& val) const;
查看是否存在某个数据
void test()
{
vector<int> vec = { 4, 3, 9, 6, 3, 10, 12, 50, 1 };
set<int> set2 = { vec.begin(), vec.end() };
cout << set2.count(4) << endl;
cout << set2.count(40) << endl;
}
测试:
其他
set默认是一个递增的序列,我们可以手动修改成递减的序列
void printSet(const set<int, greater<int>>& set)
{
for (auto& s : set)
cout << s << " ";
cout << endl;
}
void test()
{
vector<int> vec = { 4, 3, 9, 6, 3, 10, 12, 50, 1 };
set<int, greater<int>> set2 = { vec.begin(), vec.end() };
printSet(set2);
}
测试:
map
map是STL的一个关联容器,它提供一对一的hash。自动建立key - value的对应。key 和 value可以是任意你需要的类型,包括自定义类型。
特性:
- 并且在map的内部,key与value通过成员类型value_type绑定在一起, 为其取别名称为pair
- map中的元素总是按照键值key进行比较排序的,默认为递增排序
- map支持下标访问符,即在[]中放入key,就可以找到与key对应的value
- map中的key不可以重复,但是value可以重复。不能修改key,但是可以修改value
模板参数
Key:key值的类型
T:value值的类型
构造函数
explicit map (const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type()); 空构造
template < class InputIterator>
map (InputIterator first, InputIterator last, const key_compare& comp = key_compare(), 通过迭代器创建map容器
template <class T1, class T2>
void printMap(const map<T1, T2>& m)
{
//map中的数据pair,不能直接解引用获得值
typename map<T1, T2>:: const_iterator it = m.begin();
while (it != m.end())
{
cout << it->first << "-->" << it->second << endl;
++it;
}
}
void test()
{
map<int, int> map1;//空的map容器
pair<int, int> arr[] = {pair<int ,int>(1, 3), pair<int ,int>(1, 2) ,
pair<int ,int>(3, 3) , pair<int ,int>(0, 0), pair<int ,int>(5, 5) };
map<int, int> map2(arr, arr+sizeof(arr) / sizeof(arr[0]));//通过数据创建迭代器
printMap(map2);
}
测试:key值一样不能存入。迭代器的访问底层也是一个中序遍历,按照key的递增序列的遍历
map的迭代器可以修改value,但是不可以修改key
void test()
{
pair<int, int> arr[] = { pair<int ,int>(1, 3), pair<int ,int>(1, 2) ,
pair<int ,int>(3, 3) , pair<int ,int>(0, 0), pair<int ,int>(5, 5) };
map<int, int> map1(arr, arr+sizeof(arr) / sizeof(arr[0]));
printMap(map1);
cout << "修改第一个数据的value" << endl;
auto it = map1.begin();//第一个数据
it->second = 10;
//it->first = 2; error
printMap(map1);
}
测试:
[]方括号
mapped_type& operator[] (const key_type& k);
和我们平时使用数组时使用方法类似,key相当于索引,value就是索引对应的值 map[key] == value
void test()
{
pair<int, int> arr[] = { pair<int ,int>(1, 3), pair<int ,int>(1, 2) ,
pair<int ,int>(3, 3) , pair<int ,int>(0, 0), pair<int ,int>(5, 5) };
map<int, int> map1(arr, arr + sizeof(arr) / sizeof(arr[0]));
printMap(map1);
cout << map1[1] << endl;
map1[1] = 100;
cout << map1[1] << endl;
}
测试:
但是map中的[]具有新的功能,即使key不存在,也可以通过[]来插入新的一个键值对并输出对应的value值
void test()
{
pair<int, int> arr[] = { pair<int ,int>(1, 3), pair<int ,int>(1, 2) ,
pair<int ,int>(3, 3) , pair<int ,int>(0, 0), pair<int ,int>(5, 5) };
map<int, int> map1(arr, arr + sizeof(arr) / sizeof(arr[0]));
map1[10] = 100;//插入一个key为10,value为100的数据
cout << map1[10] << endl;
printMap(map1);
}
测试:
我们通过这个接口底层实现来理解为什么可以通过[]来插入数据
其实map进行[]操作就等于进行对下面这行代码进行操作
(\*((this->insert(make\_pair(k,mapped\_type()))).first)).second
我们来分解一下
1.先执行mapped_type(),也就是value类型的缺省值
2.执行make_pair(k,mapped_type()),创建一个键值对pair对象
3.执行insert(make_pair(k,mapped_type())), 插入这个创建好的pair对象,并返回pair<iterator,bool>,其中iterator是新插入的key对应迭代器
4.执行(this->insert(make_pair(k,mapped_type()))).first,调用返回的pair<iterator,bool>第一个元素iterator
5.执行*((this->insert(make_pair(k,mapped_type()))).first),对迭代器进行解引用获得pair对象pair<int, int>
6.执行(*((this->insert(make_pair(k,mapped_type()))).first)).second,调用pair对象的第二个元素,也就是value
如果key值已经存在,insert插入失败会返回已经存在的pair< iterator, bool>,其中iterator是已经存在的键为key的pair的迭代器
at接口
mapped_type& at (const key_type& k);
void test()
{
pair<int, int> arr[] = { pair<int ,int>(1, 3), pair<int ,int>(1, 2) ,
pair<int ,int>(3, 3) , pair<int ,int>(0, 0), pair<int ,int>(5, 5) };
map<int, int> map1(arr, arr + sizeof(arr) / sizeof(arr[0]));
//at接口和operator[]的区别就在于at执行插入对象存在时抛异常
cout << map1.at(10) << endl;
}
insert
pair<iterator,bool> insert (const value_type& val);
void test()
{
map<int, int> map1;
auto ret = map1.insert(pair<int, int>(1, 1));
cout << ret.first->first << "-->" << ret.first->second << "insert:" << ret.second << endl;
ret = map1.insert(make\_pair(2, 2));
cout << ret.first->first << "-->" << ret.first->second << "insert:" << ret.second << endl;
//key值存在插入失败
ret = map1.insert(make\_pair(2, 3));
cout << ret.first->first << "-->" << ret.first->second << "insert:" << ret.second << endl;
}
测试:
erase
size_type erase (const key_type& k);
void test()
{
pair<int, int> arr[] = { pair<int ,int>(1, 3), pair<int ,int>(1, 2) ,
pair<int ,int>(3, 3) , pair<int ,int>(0, 0), pair<int ,int>(5, 5) };
map<int, int> map1(arr, arr + sizeof(arr) / sizeof(arr[0]));
size_t num = map1.erase(3);//存在返回1
cout << num << endl;
num = map1.erase(2);//不存在返回0
cout << num << endl;
}
测试:
multiset
与set类似,但是存的值可以重复
特性:
- multiset是按照特定顺序存储元素的容器,其中元素是可以重复的。
- multiset元素的值不能在容器中进行修改(因为元素 总是const的),但可以从容器中插入或删除
- 默认排序依然是递增
操作
void test()
{
int arr[] = { 1, 6, 8, 5, 4, 9, 2, 4, 9 };
multiset<int> ms(arr, arr + sizeof(arr) / sizeof(arr[0]));
for (auto& e : ms)
{
cout << e << " ";
}
cout << endl;
}
multimap
与map类似,但是存的key值可以重复
特性:
- Multimaps是关联式容器,它按照特定的顺序,存储由key和value映射成的键值对<key, value>,其中 多个键值对之间的key是可以重复的
- 默认排序依然是递增
操作
void test()
{
multimap<int, int> mm;
mm.insert(make\_pair(10, 10));
mm.insert(make\_pair(20, 20));
mm.insert(make\_pair(10, 30));
mm.insert(make\_pair(10, 40));
mm.insert(make\_pair(10, 50));
mm.insert(make\_pair(50, 60));
mm.insert(make\_pair(40, 70));
mm.insert(make\_pair(30, 80));
for (auto& e : mm)
{
cout << e.first << "-->" << e.second << endl;
}
}
测试:multimap不存在[]的操作
练习题
题目:
思路:
0、示例如下
1、将单词存入到map<string ,int>中,此时单词在mp中的存的是按照字符升序,且带有出现频率的map容器
2、创建一个,multimap容器,类型为multimap<int ,string, greater< int>>。将mp中的key存在mf中的value中,将mp中的value存在mf中的key中