一、关联容器:
按关键字有序保存元素
map 关联数组;保存关键字-值对
set 关键字即值,只保存关键字的容器
multimap 关键字可以重复出现的map
multiset 关键字可以重复出现的set
无序关联容器
unordered_map 用哈希函数组织的map,无序
unordered_set 用哈希函数组织的set,无序
unordered_multimap 哈希组织的map;关键字可以重复
unordered_multiset 哈希组织的set,关键字可以重复
说明:
1、map容器:map的底层是由红黑树实现的,红黑树的每一个节点都代表着map的一个元素。该数据结构具有自动排序的功能,因此map内部的元素都是有序的,元素在容器中的顺序是通过比较键值确定的。默认使用 less<K> 对象比较。
2、multimap容器:与map容器类似,区别只在于multimap容器可以保存键值相同的元素。
3、unordered_map容器:该容器的底层是由哈希(又名散列)函数组织实现的。元素的顺序并不是由键值决定的,而是由键值的哈希值确定的,哈希值是由哈希函数生成的一个整数。利用哈希函数,将关键字的哈希值都放在一个桶(bucket)里面,具有相同哈希值的放到同一个桶。unordered_map内部元素的存储是无序的,也不允许有重复键值的元素,相当于java中的HashMap。
4、unordered_multimap容器:也可以通过键值生成的哈希值来确定对象的位置,但是它允许有重复的元素。
map和multimap容器的模板都定义在map头文件中,unordered_map和unordered_multimap容器的模板都定义在unordered_map头文件中中。
multi前缀表明键值不必唯一,但是如果没有这个前缀,键值必须唯一。
unordered前缀表明容器中元素的位置是通过其键值所产生的哈希值来决定的,而不是通过比较键值决定的,即容器中的元素是无序的。如果没有这个前缀,则容器中元素是由比较键值决定的,即有序。
二、map容器
2.1 map初始化:
map<string, string> authors = { {"Joyce", "James"}, {"Austen", "Jane"}, {"Dickens", "Charles"} };
2.2 插入数据
1)insert
map<string, int> mapStudent;//创建map
mapStudent.insert(pair<string, int>("student_one", 22));
或者使用make_pair
map<string, int> mapStudent;
mapStudent.insert(make_pair("student_one", 22));
2)map<string, int> mapStudent;//创建map
mapStudent.insert(map<string, int>::value_type("student_one", 22));
3)数组方式
map<string, int> mapStudent;//创建map
mapStudent["student_one"] = 22;
3)数据的访问和遍历
map访问和查找元素的常用方法有:
==========================================================================================
operator[] 访问元素,也可以用于修改某个元素的value值;不进行下标(关键字)是否存在的检查(即如果关键字不存在,程序运行不会出错),访问到某个元素时,
如果该元素的键值不存在则直接创建该元素,返回是初始的值(比如int型的初始为0,则返回0,string初始为NULL,则返回NULL)
at 访问元素,也可以用于修改某个元素的value值;会进行下标(关键字)是否存在的检查,如果关键字不存在,则会拋出 out_of_range 异常。
==========================================================================================
利用迭代器访问元素
******************************************************************************************
map<K, T>::iterator it;
(*it).first; // the key value (of type Key)
(*it).second; // the mapped value (of type T)
(*it); // the "element value" (of type pair<const Key,T>)
元素的键值和value值分别是迭代器的first和second属性。也可以用迭代器指针直接访问。
it->first; // same as (*it).first (the key value)
it->second; // same as (*it).second (the mapped value)
迭代器的成员函数:
begin 返回指向容器起始位置的迭代器(iterator)
end 返回指向容器末尾位置的迭代器
cbegin 返回指向容器起始位置的常迭代器(const_iterator)
cend 返回指向容器末尾位置的常迭代器(当不需要对元素进行写访问时使用常迭代器)
rbegin 返回指向容器起始位置的反向迭代器(reverse_iterator)
rend 返回指向容器末尾位置的反向迭代器
#########################################################################################
查找某键值的元素是否存在:
count 若存在,返回1;不存在返回0
find 若存在返回指向元素的迭代器指针,不存在返回end()
4) map遍历
① 使用前向迭代器遍历map
map<string, int>::iterator iter;
for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
cout << iter->first << " " << iter->second << endl;
for (map<string, int>::iterator iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
cout << (*iter).first << " " << (*iter).second << endl;
这两种形式的访问都是可以改变元素中的value值的,即可以进行写访问:
map<string, int> mapStudent;//创建map
mapStudent["student_one"] = 22;
mapStudent["student_two"] = 25;
mapStudent["student_three"] = 21;
map<string, int>::iterator iter;
for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
(*iter).second = 100; //将mapStudent中的元素value值全部改为100
for (iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
cout << iter->first << " " << iter->second << endl; //遍历
如果改用const_iterator,则两种方式都不能进行写访问。
② 使用反向迭代器遍历map
map<string, int>::reverse_iterator iter;
for (iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++)
cout << iter->first << " " << iter->second << endl; //反向遍历
③ 使用auto关键字
for (auto it = mapStudent.begin(); it != mapStudent.end(); it++)
cout << it->first << " " << it->second << endl; //遍历
④ 使用数组的方式遍历数组
5)数据删除
使用erase函数
int res = mapStudent.erase("student_one"); //删除成功返回1,失败返回0;只有使用关键字删除时才有返回值
cout << "res=" << res << endl;
//使用迭代器删除
map<string, int>::iterator iter;
iter = mapStudent.find("student_two");
mapStudent.erase(iter);
//使用迭代器删除一个范围的元素
auto it = mapStudent.begin();
mapStudent.erase(it, mapStudent.find("student_two"));
三、multimap容器
multimap容器保存的是有序的键/值对,但是可以保存重复的元素。multimap中会出现具有相同键值的元素序列。multimap大部分成员函数的使用方式和map相同。因为重复键的原因,multimap有一些函数的使用方式和map有一些区别。
1、访问元素
multimap 不支持下标运算符,因为键并不能确定一个唯一元素。和 map 相似,multimap 也不能使用 at() 函数。