1.map
2.multimap
3.unordered_map
4.unordered_multimap
1.map支持下标访问符,即在[]中放入key,就可以找到与key对应的value
2.map通常被实现为二叉搜索树(更准确的说:平衡二叉搜索树(红黑树)
3.键的值相同的元素不能重复
map people4{ {"Ann", 25}, {"Bill", 36}, {"Bill", 46}, {"Bill", 56},{"Jack", 32},{"Jill", 32} };
for (auto e : people4) {
cout << e.first << " " << e.second << endl;
}
//out:
Ann 25
Bill 36
Jack 32
Jill 32
4.键的值无法修改,只能改变值
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
map::iterator e = people.begin();
e->second = 18; //true
e->first = "Niuniu"; //error
5.map会根据键排序,可以通过迭代器得到按键排序的结果(因为map底层的实现是红黑树)
map people{ {88, "Fuu"}, { 26, "Ann"}, {46, "Bill"},{ 32,"Jack"} };
map::const_iterator it = people.cbegin();
while (it != people.cend()) {
cout << it->first << " " << it->second << endl;
it++;
}
cout << endl;
/*out:
26 Ann
32 Jack
46 Bill
88 Fuu
*/
6.通过不存在的键访元素将会插入所访问的不存在的键值对,并且值给默认值
map people{ {88, "Fuu"}, { 26, "Ann"}, {46, "Bill"},{ 32,"Jack"} };
cout << people[64] << endl; //不做边界检查,会插入pair(64,"\0")--> 通过不存在的键访元素将会插入所访问的不存在的键值对,并且值给默认值
for (auto e : people)
cout << e.first << " " << e.second << endl;
cout << endl;
/*out:
26 Ann
32 Jack
46 Bill
64
88 Fuu
*/
通过at()接口可以对边界做检查,不会导致插入不存在的元素, 访问键不存在的元素编译器会报错
map people{ {88, "Fuu"}, { 26, "Ann"}, {46, "Bill"},{ 32,"Jack"} };
cout << people。at(64) << endl; //对边界做检查
for (auto e : people)
cout << e.first << " " << e.second << endl;
cout << endl;
/*out:
26 Ann
32 Jack
46 Bill
88 Fuu
*/
map定义及初始化
1.定义一个空map
map people1;
2.用初始化列表来指定 map 的初始值
map people2{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
3.utility 头文件中定义了make_pair
map people3{ make_pair("Ann",25),make_pair("Bill", 46),make_pair("Jack", 32),make_pair("Jill", 32) };
4.map
map personnel1{ people2 }; //Duplicate people2 map
5.可以用另一个容器的一段元素来创建一个map,用开始和结束迭代器以通常的方式指定元素。显然,迭代器指向的pair元素的类型必须和容器兼容。
map personnel2{ begin(people1),end(people1) };
//people1.end(); 等价于 end(people1)
6.当然,也可以用另一个容器的元素子集来创建容器:左闭右开[iterator1 , iterator2 )
map::iterator it1 = people2.begin();
map::iterator it2 = people2.find("Jack");
map personnel3{it1 , it2 };
map::iterator e = personnel3.begin();
插入
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
//首先定义一个pair
pair p("yang", 20);
//然后插入,只能成功插入键值不同的元素(特性:map相同键值的元素不重复)
people.insert(p);
//或者
people.insert(pair("yang", 20));
for (auto e : people)
cout << e.first << " " << e.second << endl;
删除
1.直接通过键值删除元素
people.erase("yang");
2.通过迭代器删除迭代器所迭代的元素
map::iterator it = people.find("yang");
people.erase(it);
3.删除两个迭代器区间上的元素
map::iterator it1 = people.find("Bill");
map::iterator it2 = people.find("Jill");
people.erase(it1, it2);
修改:通过[key]直接修改, 如果修改的键值对不存在则会插入
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
people[Ann] = 16; //修改
people[yzy] = 20; //插入
求容量及判空
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
//容量
cout << people.size() << endl; //4
//判空
cout << people.empty() << endl; //0
清空
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
people.clear();
cout << people.size() << endl; //0
交换
map people1{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
map people2{ {"Fuu", 26}, {"Sansan", 32} };
people1.swap(people2);
遍历
1.利用C++ auto
(1).不加const
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
for (auto e : people) {
e.second = 16;
cout << e.first <<" "<< e.second << endl;
}
cout << endl;
/*out:
Ann 16
Bill 16
Jack 16
Jill 16
*/
for (auto e : people) {
cout << e.first << " " << e.second << endl;
}
cout << endl;
/*out:
Ann 25
Bill 46
Jack 32
Jill 32
*/
实际上只是改变了输出结果
(1).加const
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
for (const auto e : people) {
cout << e.first << e.second << endl;
//e.second = 16; //error
}
cout << endl;
auto关键字遍历的话,如果给auto关键字前面加上const,for (const auto e : people) 那么就无法通过e来修改值了
2.利用迭代器
(1).正向迭代器
map
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
map::iterator e = people.begin();
while (e != people.end()) {
cout << e->first << " "<< e->second<
(2).正向常迭代器, 不能通过迭代器修改值
map
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
map::const_iterator e = people.cbegin();
//e->second = 17; //error
while (e != people.cend()) {
cout << e->first << " " << e->second << endl;
e++;
}
(3).反向迭代器,可以通过迭代器修改值
map
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
map::reverse_iterator e = people.rbegin(); //可以通过迭代器修改值
e->second = 16;
while (e != people.rend()) {
cout << e->first << " " << e->second << endl;
e++;
}
(4).反向常迭代器,不可以通过迭代器修改值
map
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
map::const_reverse_iterator e = people.crbegin();
//e->second = 16; //error
while (e != people.crend()) {
cout << e->first << " " << e->second << endl;
e++;
}
3.利用重载的运算符[]访问([]中是键, 返回值是值)
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
size_t age = people["Ann"];
cout << age <
auto关键字遍历的话,是用点访问键和值,迭代器的话是用箭头访问键和值
查找 时间复杂度为:
log_2 n
只能通过键值来查找,返回类型是迭代器
map people{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
map::iterator it3 = people.find("Ann");//找到就会返回迭代
//error:不能通过键值对的值来查找
map::iterator it3 = people.find(25);
//找不到迭代器就会走到end()
map::iterator it4 = people.find("Fuu");
if (it4 == end(people))
cout << "not found" << endl;
#include
1.multimap在底层用二叉搜索树(红黑树)来实现。在内部,multimap中的元素总是通过其内部比较对象,按照指定的特定严格弱排序标准对key进行排序 的。
2.multiset容器通过key访问单个元素的速度通常比比unordered_multiset容器慢
3.键的值相同的元素可以重复
pair value[] = {
{"111", "abc"},
{"555","xyz"},
{"222", "opq"},
{"222", "opq"},
{"222", "opq"}
};
multimap multiMap;
for (int i = 0; i < (sizeof(value) / sizeof(pair)); i++)
multiMap.insert(value[i]);
multimap::iterator it = multiMap.begin();
while (it != multiMap.end()) {
cout << it->first << " ";
cout<< it++->second << endl;
}
/*out:
111 abc
222 opq
222 opq
222 opq
555 xyz
*/
4.不可以以[key]的方式访问键值对的值
multimap定义及初始化(与map的定义及初始化方式一样)
容量及判空 清空 交换 遍历 都相似
插入:可以插入键的值相同的元素
删除:会删除键的值相同的所有元素
修改:不允许
multimap people{ {"Ann", 25},{"Ann", 18}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
people["Bill"] = 100; //error
查找:返回键值相同的元素中迭代顺序第一个的元素,找不到迭代器走到end()
pair value[] = {
{"111", "abc"},
{"555","xyz"},
{"222", "opq"},
{"222", "exo"},
{"222", "nha"}
};
multimap multiMap;
for (int i = 0; i < (sizeof(value) / sizeof(pair)); i++)
multiMap.insert(value[i]);
multimap::iterator find = multiMap.find("222");
cout << find->first <<" "<< find->second <::iterator find2 = multiMap.find("999");
if (find2 == multiMap.end())
cout << "Not found" << "iterator has pointed the end" << endl;
/*out:
Not founditerator has pointed the end
*/
#include
1.在内部,unordered_map没有对
2.unordered_map容器通过key访问单个元素要比map快,但它通常在遍历元素子集的范围迭代方面效率较低。
3.unordered_maps实现了直接访问操作符(operator[]),它允许使用key作为参数直接访问value。若使用key作为参数直接访问value时,当不存在key对应的键值对时,就会插入值为默认值的键值对。
4.相较于map,unordered_map具有桶操作(map平衡化的红黑树, unordered_map哈希结构)
unordered_map定义及初始化(与map的定义及初始化方式一样)
1.定义一个空unordered_map
unordered_map people1;
2.用初始化列表来指定 unordered_map 的初始值
unordered_map people2{ {"Ann", 25}, {"Bill", 46},{"Jack", 32},{"Jill", 32} };
3.utility 头文件中定义了make_pair
unordered_map people3{ make_pair("Ann",25),make_pair("Bill", 46),make_pair("Jack", 32),make_pair("Jill", 32) };
4.map
unordered_map personnel1{ people2 }; //Duplicate people2 map
5.可以用另一个容器的一段元素来创建一个unordered_map,用开始和结束迭代器以通常的方式指定元素。显然,迭代器指向的pair元素的类型必须和容器兼容。
unordered_map personnel2{ begin(people1),end(people1) };
//people1.end(); 等价于 end(people1)
6.当然,也可以用另一个容器的元素子集来创建容器:左闭右开[iterator1 , iterator2 )
unordered_map::iterator it1 = people2.begin();
unordered_map::iterator it2 = people2.find("Jack");
unordered_map personnel3{it1 , it2 };
unordered_map::iterator e = personnel3.begin();
插入 删除 容量及判空 清空 交换 查找都相似
遍历:只有正向的迭代器和正向的常迭代器
(1).正向的迭代器
unordered_map unorderedMap = { {"Ann", 25},{"Fuu", 18}, {"Bill", 46} };
unordered_map::iterator it = unorderedMap.begin();
while (it != unorderedMap.end()) {
cout << it->first << " ";
cout<< it++->second << endl;
}
cout << endl;
(2).正向的常迭代器
unordered_map unorderedMap = { {"Ann", 25},{"Fuu", 18}, {"Bill", 46} };
unordered_map::const_iterator cit = unorderedMap.cbegin();
while (cit != unorderedMap.cend()) {
cout << cit->first << " ";
cout<< cit++->second << endl;
}
修改:
unordered_map unorderedMap = { {"Ann", 25},{"Fuu", 18}, {"Bill", 46} };
unorderedMap["Ann"] = 24;
unordered_map的桶操作:
1.求桶的总个数
unordered_map unorderedMap;
pair val[] = {
{"111", "aaa"},
{"222", "bbb"},
{"222", "ddd"},
{"222", "uuu"},
{"333", "ccc"},
{"333", "fff"}
};
for (int i = 0; i < (sizeof(val) / sizeof(pair)); i++)
unorderedMap.insert(val[i]);
//求桶的总个数
cout<<"bucket cout: "<
2.根据key值求元素在几号桶中
cout << "find the element in which bucket that key is ""333"" " << unorderedMap.bucket("333") <
3.求几号桶的size(元素个数)
cout<<"one of the buckets size: "<
unordered_multimap
#include <>
unordered_multimap特点(与multimap的区别是)
1.值可以重复,会将哈希值的键值对放在相同的桶中。unordered系列容器底层都使用了哈希结构,元素访问效率高
2.multimap都没有[key]访问元素的功能,也就是没有重载[]
unordered_multimap用法
定义及初始化(与multimap的定义及初始化方式一样)
插入(因为没用重载[],因此不能通过不存在的键值访问,从而插入元素)
删除 (会删除值相同的所有元素)
容量及判空 清空 交换 查找都相似
遍历:只有正向的迭代器和正向的常迭代器
(1).正向的迭代器
unordered_multimap unorderedMultiMap;
pair val[] = {
{ "111", "aaa" },
{ "222", "bbb" },
{ "333", "ccc" },
{ "444", "ddd"}
};
for (int i = 0; i < (sizeof(val) / sizeof(pair)); i++)
unorderedMultiMap.insert(val[i]);
unordered_multimap::iterator it = unorderedMultiMap.begin();
//it->first = "888"; //error
it->second = "uuu";
while (it != unorderedMultiMap.end()) {
cout << it->first << " ";
cout << it++->second << endl;
}
cout << endl;
(2).正向的常迭代器
unordered_multimap::const_iterator cit = unorderedMultiMap.cbegin();
//cit->first = "999"; //error
//cit->second = "uuu"; //error
while (cit != unorderedMultiMap.cend()) {
cout << cit->first << " ";
cout<< cit++->second << endl;
}
cout << endl;
修改:(由于没有对[]重载,因此只能通过迭代器来修改)
并且修改的值是哈希桶中第一个元素的值,并没有修改匹配的所有值。
unordered_multimap::iterator find = unorderedMultiMap.find("222");
find->second = "kkk";
unordered_map的桶操作:
1.求桶的总个数
unordered_multimap unorderedMap;
pair val[] = {
{"111", "aaa"},
{"222", "bbb"},
{"222", "ddd"},
{"222", "uuu"},
{"333", "ccc"},
{"333", "fff"} };
for (int i = 0; i < (sizeof(val) / sizeof(pair)); i++)
unorderedMultiMap.insert(val[i]);
//求桶的总个数
cout<<"bucket cout: "<
2.根据key值求元素在几号桶中
cout << "find the element in which bucket that key is ""333"" " << unorderedMultiMap.bucket("333") << endl;
3.求几号桶的size(元素个数)
cout << "one of the buckets[0] size: " << unorderedMultiMap.bucket_size(0) << endl;
//访问所有桶的size
for (int i = 0; i < unorderedMultiMap.bucket_count(); i++)
cout << "bucket[" << i << "]" << " size = " << unorderedMultiMap.bucket_size(i) << endl;