map、multimap和unordered_map容器 map基本概念 简介:
map中所有元素都是pair
pair
中第一个元素为key
(键值),起到索引作用,第二个元素为value
(实值)
所有元素都会根据元素的键值自动排序
本质:
map/multimap
属于关联式容器 ,底层结构是基于红黑树实现。
优点:
map和multimap区别:
map
不允许容器中有重复key值元素
multimap
允许容器中有重复key值元素
map构造和赋值 使用map前要包含头文件:
功能描述:
函数原型:
构造:
map<T1, T2> mp;
//map默认构造函数:
map(const map &mp);
//拷贝构造函数
赋值:
map& operator=(const map &mp);
//重载等号操作符
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <iostream> #include <map> using namespace std;void printMap (map<int ,int >&m) { for (map<int , int >::iterator it = m.begin (); it != m.end (); it++) { cout << "key = " << it->first << " value = " << it->second << endl; } cout << endl; } void test01 () { map<int ,int >m; m.insert (pair<int , int >(1 , 10 )); m.insert (pair<int , int >(2 , 20 )); m.insert (pair<int , int >(3 , 30 )); printMap (m); map<int , int >m2 (m); printMap (m2); map<int , int >m3; m3 = m2; printMap (m3); } int main () { test01 (); system ("pause" ); return 0 ; }
输出:
1 2 3 4 5 6 7 8 9 10 11 key = 1 value = 10 key = 2 value = 20 key = 3 value = 30 key = 1 value = 10 key = 2 value = 20 key = 3 value = 30 key = 1 value = 10 key = 2 value = 20 key = 3 value = 30
总结:map中所有元素都是成对出现,插入数据时候要使用对组
map大小和交换 功能描述:
函数原型:
size();
//返回容器中元素的数目
empty();
//判断容器是否为空
swap(st);
//交换两个集合容器
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 #include <iostream> #include <map> using namespace std;void printMap (map<int ,int >&m) { for (map<int , int >::iterator it = m.begin (); it != m.end (); it++) { cout << "key = " << it->first << " value = " << it->second << endl; } cout << endl; } void test01 () { map<int , int >m; m.insert (pair<int , int >(1 , 10 )); m.insert (pair<int , int >(2 , 20 )); m.insert (pair<int , int >(3 , 30 )); if (m.empty ()) { cout << "m为空" << endl; } else { cout << "m不为空" << endl; cout << "m的大小为: " << m.size () << endl; } } void test02 () { map<int , int >m; m.insert (pair<int , int >(1 , 10 )); m.insert (pair<int , int >(2 , 20 )); m.insert (pair<int , int >(3 , 30 )); map<int , int >m2; m2.insert (pair<int , int >(4 , 100 )); m2.insert (pair<int , int >(5 , 200 )); m2.insert (pair<int , int >(6 , 300 )); cout << "交换前" << endl; printMap (m); printMap (m2); cout << "交换后" << endl; m.swap (m2); printMap (m); printMap (m2); } int main () { test01 (); test02 (); system ("pause" ); return 0 ; }
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 m不为空 m的大小为: 3 交换前 key = 1 value = 10 key = 2 value = 20 key = 3 value = 30 key = 4 value = 100 key = 5 value = 200 key = 6 value = 300 交换后 key = 4 value = 100 key = 5 value = 200 key = 6 value = 300 key = 1 value = 10 key = 2 value = 20 key = 3 value = 30
总结:
统计大小 — size
判断是否为空 — empty
交换容器 — swap
map插入和删除 功能描述:
函数原型:
insert(elem);
//在容器中插入元素。
clear();
//清除所有元素
erase(pos);
//删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(key);
//删除容器中值为key的元素。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #include <iostream> #include <map> using namespace std;void printMap (map<int ,int >&m) { for (map<int , int >::iterator it = m.begin (); it != m.end (); it++) { cout << "key = " << it->first << " value = " << it->second << endl; } cout << endl; } void test01 () { map<int , int > m; m.insert (pair<int , int >(1 , 10 )); m.insert (make_pair (2 , 20 )); m.insert (map<int , int >::value_type (3 , 30 )); m[4 ] = 40 ; printMap (m); m.erase (m.begin ()); printMap (m); m.erase (3 ); printMap (m); m.erase (m.begin (),m.end ()); m.clear (); printMap (m); } int main () { test01 (); system ("pause" ); return 0 ; }
输出:
1 2 3 4 5 6 7 8 9 10 11 key = 1 value = 10 key = 2 value = 20 key = 3 value = 30 key = 4 value = 40 key = 2 value = 20 key = 3 value = 30 key = 4 value = 40 key = 2 value = 20 key = 4 value = 40
总结:
插入 — insert
删除 — erase
清空 — clear
map查找和统计 功能描述:
函数原型:
find(key);
//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
count(key);
//统计key的元素个数
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <iostream> #include <map> using namespace std;void test01 () { map<int , int >m; m.insert (pair<int , int >(1 , 10 )); m.insert (pair<int , int >(2 , 20 )); m.insert (pair<int , int >(3 , 30 )); map<int , int >::iterator pos = m.find (3 ); if (pos != m.end ()) { cout << "找到了元素 key = " << (*pos).first << " value = " << (*pos).second << endl; } else { cout << "未找到元素" << endl; } int num = m.count (3 ); cout << "num = " << num << endl; } int main () { test01 (); system ("pause" ); return 0 ; }
输出:
1 2 找到了元素 key = 3 value = 30 num = 1
总结:
查找 — find (返回的是迭代器)
统计 — count (对于map,结果为0或者1)
map容器排序 学习目标:
map容器默认排序规则为 按照key值进行 从小到大排序,掌握如何改变排序规则
主要技术点:
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 #include <map> class MyCompare {public : bool operator () (int v1, int v2) { return v1 > v2; } }; void test01 () { map<int , int , MyCompare> m; m.insert (make_pair (1 , 10 )); m.insert (make_pair (2 , 20 )); m.insert (make_pair (3 , 30 )); m.insert (make_pair (4 , 40 )); m.insert (make_pair (5 , 50 )); for (map<int , int , MyCompare>::iterator it = m.begin (); it != m.end (); it++) { cout << "key:" << it->first << " value:" << it->second << endl; } } int main () { test01 (); system ("pause" ); return 0 ; }
输出:
1 2 3 4 5 key:5 value:50 key:4 value:40 key:3 value:30 key:2 value:20 key:1 value:1
总结:
利用仿函数可以指定map容器的排序规则
对于自定义数据类型,map必须要指定排序规则,同set容器
unordered_map的使用 map和unordered_map区别: map的优点及缺点:
优点:
①、map
基于红黑树实现,红黑树具有自动排序的功能 ,因此map内部所有的数据,在任何时候,都是有序的 ;
②、map
内部实现基于红黑树,使得map的很多操作在lgn
的时间复杂度下就可以实现,因此效率非常的高 。
缺点:
空间占用率高 ,因为map内部基于红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间。
应用场景:适用于有顺序要求的问题,使用map会更高效一些;
unordered_map的优点及缺点:
优点:
unordered_map
内部基于哈希表,所以数据插入和查找的时间复杂度很低,几乎是常数时间
缺点:
代价是消耗比较多的内存,无自动排序功能。 底层实现上,使用一个下标范围比较大的数组来存储元素,形成很多的桶,利用hash
函数对key
进行映射到不同区域进行保存。
应用场景:对于查找问题,unordered_map
会更加高效一些。
map和unordered_map的使用
unordered_map
的用法和map
是一样的,提供了 insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <string> #include <iostream> #include <unordered_map> using namespace std;int main () { unordered_map<string, int > M; M.insert (pair<string, int >("A" , 1 )); M.insert (unordered_map<string, int >::value_type ("B" , 2 )); M["C" ] = 3 ; if (M.empty ()) cout << "无元素" << endl; else cout << "有" << M.size () << "个元素" << endl; unordered_map<string, int >::iterator iter; for (iter = M.begin (); iter != M.end (); iter++) cout << iter->first << ends << iter->second << endl; if (M.count ("A" ) == 0 ) cout << "can't find A!" << endl; else cout << "find A!" << endl; if ((iter = M.find ("B" )) != M.end ()) cout << "B=" << iter->second << endl; else cout << "can't find B!" << endl; return 0 ; }
输出:
1 2 3 4 5 6 有3 个元素 A1 B2 C3 find A! B=2
例:leetcode3.无重复字符的最长子串
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 #include <iostream> #include <algorithm> #include <vector> #include <string> #include <unordered_map> using namespace std;class Solution { public : int lengthOfLongestSubstring (vector<char >& s) { int res = 0 ; size_t left = 0 ; unordered_map<char , size_t > m; for (int i = 0 ; i < s.size (); i++) { left = max (left, m[s[i]]); m[s[i]] = i + 1 ; res = max (res, int (i - left + 1 )); } return res; } }; int main () { vector<char > str; string s = "abcdabcdbb" ; for (int i = 0 ; i < s.size (); i++) { str.push_back (s[i]); } Solution S1; int nums = S1.lengthOfLongestSubstring (str); cout << "最长无重复子串的长度为: " << nums << endl; return 0 ; }
输出: