unordered_map
c++
1.std::unordered_map 的定义与特性 所在头文件:
std::unorederd_map 类模板:
1 2 3 4 5 6 template < class Key , // unordered_map : :key_type class T , // unordered_map : :mapped_type class Hash = hash <Key>, // unordered_map : :hasher class Pred = equal_to <Key>, // unordered_map : :key_equal class Alloc = allocator < pair<const Key,T> > // unordered_map : :allocator_type > class unordered_map ;
关联性:std::unorederd_map 是一个关联容器,其中的元素根据键来引用,而不是根据索引来引用。
无序性:在内部,std::unordered_map中的元素不会根据其键值或映射值按任何特定顺序排序,而是根据其哈希值组织到桶中,以允许通过键值直接快速访问各个元素(常量的平均时间复杂度)。
唯一性:std::unorederd_map中的元素的键是唯一的。
2.构造 std::unordered_map 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 #include <iostream> #include <string> #include <unordered_map> typedef std ::unordered_map <std ::string ,std ::string > stringmap;stringmap merge (stringmap a,stringmap b) { stringmap temp (a) ; temp.insert(b.begin (),b.end ()); return temp; }int main () { stringmap first; stringmap second ( {{"apple" ,"red" }, {"lemon" ,"yellow" }} ) ; stringmap third ( {{"orange" ,"orange" }, {"strawberry" ,"red" }, {"apple" ,"green" }} ) ; stringmap fourth (second) ; stringmap fifth (merge(third,fourth)) ; stringmap sixth (fifth.begin (),fifth.end ()) ; std ::cout << "sixth contains:" ; for (auto & x: sixth) std ::cout << " " << x.first << ":" << x.second; std ::cout << std ::endl ; system("pause" ); return 0 ; }
IO:
1 sixth contains: orange:orange lemon:yellow apple:green strawberry:red
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 #include <iostream> #include <string> #include <unordered_map> typedef std ::unordered_map <std ::string ,std ::string > stringmap;stringmap merge (stringmap a,stringmap b) { stringmap temp (a) ; temp.insert(b.begin (),b.end ()); return temp; }int main () { stringmap first, second, third; first = {{"AAPL" ,"Apple" }, {"MSFT" ,"Microsoft" }}; second = {{"GOOG" ,"Google" }, {"ORCL" ,"Oracle" }}; third = merge(first,second); first = third; std ::cout << "first contains:" ; for (auto & elem: first) std ::cout << " " << elem.first << ":" << elem.second; std ::cout << std ::endl ; return 0 ; }
IO:
1 first contains: GOOG:Google MSFT:Microsoft ORCL:Oracle AAPL:Apple
4.迭代器操作 4.1 指向整个容器中的元素
即,“第一个”指整个容器中的第一个,“尾后”指整个容器中的尾后。
函数声明
解释
iterator begin() noexcept; const_iterator begin() const noexcept;
返回一个迭代器,指向第一个元素
iterator end() noexcept; const_iterator end() const noexcept;
返回一个迭代器,指向尾后元素
const_iterator cbegin() const noexcept;
返回一个常量迭代器,指向第一个元素
const_iterator cend() const noexcept;
返回一个常量迭代器,指向尾后元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include <iostream> #include <unordered_map> int main () { std ::unordered_map <std ::string ,std ::string > mymap; mymap = {{"Australia" ,"Canberra" },{"U.S." ,"Washington" },{"France" ,"Paris" }}; std ::cout << "mymap contains:" ; for ( auto it = mymap.cbegin(); it != mymap.cend(); ++it ) std ::cout << " " << it->first << ":" << it->second; std ::cout << std ::endl ; std ::cout << "mymap's buckets contain:\n" ; for ( unsigned i = 0 ; i < mymap.bucket_count(); ++i) { std ::cout << "bucket #" << i << " contains:" ; for ( auto local_it = mymap.cbegin(i); local_it!= mymap.cend(i); ++local_it ) std ::cout << " " << local_it->first << ":" << local_it->second; std ::cout << std ::endl ; } return 0 ; }
IO:
1 2 3 4 5 6 7 mymap contains: France:Paris U.S.:Washington Australia:Canberra mymap' s buckets contain: bucket #0 contains: U.S.:Washington bucket #1 contains: bucket #2 contains: bucket #3 contains: France:Paris bucket #4 contains: Australia:Canberra
5. 容量操作
函数声明
解释
bool empty() const noexcept;
unordered_map 是否为空
size_type size() const noexcept;
获取unordered_map 中元素的数量
6. 访问操作
访问方式
函数声明
解释
使用方括号([])
mapped_type& operator[] (key_type&& k);
如果 k 匹配容器中某个元素的键,则该函数返回该映射值的引用。 如果 k 与容器中任何元素的键都不匹配,则该函数将使用该键插入一个新元素,并返回该映射值的引用。
使用 at()
mapped_type& at (const key_type& k); const mapped_type& at (const key_type& k) const;
如果 k 匹配容器中某个元素的键,则该函数返回该映射值的引用。 如果 k 与容器中任何元素的键都不匹配,则该函数将抛出 out_of_range 异常。
注意 :const std::unordered_map 不能使用 operator[] 操作!!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> #include <string> #include <unordered_map> int main () { std ::unordered_map <std ::string ,int > mymap = { { "Mars" , 3000 }, { "Saturn" , 60000 }, { "Jupiter" , 70000 } }; mymap.at("Mars" ) = 3396 ; mymap.at("Saturn" ) += 272 ; mymap.at("Jupiter" ) = mymap.at("Saturn" ) + 9638 ; for (auto & x: mymap) { std ::cout << x.first << ": " << x.second << std ::endl ; } return 0 ; }
IO:
1 2 3 Jupiter: 69910 Saturn: 60272 Mars: 3396
8. 删除操作
删除方式
函数声明
说明
根据元素位置
iterator erase (const_iterator position);
返回一个迭代器,指向被删除元素的后一个元素
根据元素的键
size_type erase (const key_type& k);
返回被删除元素的数目,此处为1
由一对范围迭代器指定删除的范围
iterator erase (const_iterator first, const_iterator last);
返回一个迭代器,指向最后一个被删除元素的后一个元素
删除所有元素
void clear() noexcept;
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 #include <iostream> #include <string> #include <unordered_map> int main () { std ::unordered_map <std ::string ,std ::string > mymap; mymap["U.S." ] = "Washington" ; mymap["U.K." ] = "London" ; mymap["France" ] = "Paris" ; mymap["Russia" ] = "Moscow" ; mymap["China" ] = "Beijing" ; mymap["Germany" ] = "Berlin" ; mymap["Japan" ] = "Tokyo" ; for ( auto & x: mymap ) std ::cout << x.first << ": " << x.second << std ::endl ; std ::cout << std ::endl ; mymap.erase ( mymap.begin () ); mymap.erase ("France" ); mymap.erase ( mymap.find ("U.S." ), mymap.end () ); for ( auto & x: mymap ) std ::cout << x.first << ": " << x.second << std ::endl ; system("pause" ); return 0 ; }
IO:
1 2 3 4 5 6 7 8 9 10 U.K.: London Russia: Moscow Germany: Berlin U.S.: Washington France: Paris Japan: Tokyo China: Beijing Russia: Moscow Germany: Berlin
9. 查找操作
函数声明
说明
iterator find (const key_type& k); const_iterator find (const key_type& k) const;
在容器中搜索键值等于 k 的元素,如果找到,则返回一个指向该元素的迭代器,否则返回一个指向unordered_map :: end的迭代器。
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 #include <iostream> #include <string> #include <unordered_map> int main () { std ::unordered_map <std ::string ,double > mymap = { {"mom" ,5.4 }, {"dad" ,6.1 }, {"bro" ,5.9 } }; std ::string input; std ::cout << "who? " ; getline (std ::cin ,input); std ::unordered_map <std ::string ,double >::const_iterator got = mymap.find (input); if ( got == mymap.end () ) std ::cout << "not found" ; else std ::cout << got->first << " is " << got->second; std ::cout << std ::endl ; return 0 ; }
10. 桶操作
函数声明
说明
size_type bucket_count() const noexcept;
获取容器中桶的数目
size_type bucket_size ( size_type n ) const;
获取第 n 个桶中元素的数量
size_type bucket ( const key_type& k ) const;
获取键为 k 的元素所在桶的序号
11.c++ map与unordered_map区别 需要引入的头文件不同
map: #include < map >
unordered_map: #include < unordered_map >
内部实现机理不同
map: map内部实现了一个红黑树 (红黑树是非严格平衡二叉搜索树,而AVL是严格平衡二叉搜索树),红黑树具有自动排序的功能,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。map中的元素是按照二叉搜索树(又名二叉查找树、二叉排序树,特点就是左子树上所有节点的键值都小于根节点的键值,右子树所有节点的键值都大于根节点的键值)存储的,使用中序遍历可将键值按照从小到大遍历出来。
unordered_map: unordered_map内部实现了一个哈希表 (也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)。因此,其元素的排列顺序是无序的。
优缺点以及适用处
map:
优点:
有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作 红黑树,内部实现一个红黑书使得map的很多操作在lgn的时间复杂度下就可以实现,因此效率非常的高
缺点:
空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间
适用处: 对于那些有顺序要求的问题,用map会更高效一些
unordered_map:
优点:
因为内部实现了哈希表,因此其查找速度非常的快
缺点:
哈希表的建立比较耗费时间
适用处: 对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map
总结 :
内存占有率的问题就转化成红黑树 VS hash表 , 还是unorder_map占用的内存要高。
但是unordered_map执行效率要比map高很多
对于unordered_map或unordered_set容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的
map和unordered_map的使用
unordered_map的用法和map是一样的,提供了 insert,size,count等操作,并且里面的元素也是以pair类型来存贮的。其底层实现是完全不同的,上方已经解释了,但是就外部使用来说却是一致的。
原文地址:https://blog.csdn.net/fcku_88/article/details/88353431
https://blog.csdn.net/qq_21997625/article/details/84672775