详细介绍C++STL:unordered_map

不得不提一下,hash_map未加入在C++11标准中。

在VC中编译: 

1 #include <hash_map> 2 using namespace stdext; 3 hash_map<int ,int> myhash;

 在GCC中编译:

1 #include <ext/hash_map> 2 using namespace __gnu_cxx; 3 hash_map<int ,int> myhash;

既如此,还是用unordered_map吧!

 

C++ 11标准中加入了unordered系列的容器。unordered_map记录元素的hash值,根据hash值判断元素是否相同。map相当于java中的TreeMap,unordered_map相当于HashMap。无论从查找、插入上来说,unordered_map的效率都优于hash_map,更优于map;而空间复杂度方面,hash_map最低,unordered_map次之,map最大。

unordered_map与map的对比:

  存储时是根据key的hash值判断元素是否相同,即unordered_map内部元素是无序的,而map中的元素是按照二叉搜索树存储(用红黑树实现),进行中序遍历会得到有序遍历。所以使用时map的key需要定义operator<。而unordered_map需要定义hash_value函数并且重载operator==。但是很多系统内置的数据类型都自带这些。

  总结:结构体用map重载<运算符,结构体用unordered_map重载==运算符。

unordered_map与hash_map对比:

  unordered_map原来属于boost分支和std::tr1中,而hash_map属于非标准容器。
  unordered_map感觉速度和hash_map差不多,但是支持string做key,也可以使用复杂的对象作为key。
  unordered_map编译时gxx需要添加编译选项:--std=c++11

unordered_map模板: 

复制代码
1 template < class Key, // unordered_map::key_type 2 class T, // unordered_map::mapped_type 3 class Hash = hash<Key>, // unordered_map::hasher 4 class Pred = equal_to<Key>, // unordered_map::key_equal 5 class Alloc = allocator< pair<const Key,T> > // unordered_map::allocator_type 6 > class unordered_map;
复制代码

 迭代器:

unordered_map的迭代器是一个指针,指向这个元素,通过迭代器来取得它的值。

1 unordered_map<Key,T>::iterator it; 2 (*it).first; // the key value (of type Key) 3 (*it).second; // the mapped value (of type T) 4 (*it); // the "element value" (of type pair<const Key,T>)

它的键值分别是迭代器的first和second属性。 

1 it->first; // same as (*it).first (the key value) 2 it->second; // same as (*it).second (the mapped value)

成员函数:

=================迭代器========================= 
begin   返回指向容器起始位置的迭代器(iterator) 
end      返回指向容器末尾位置的迭代器 
cbegin    返回指向容器起始位置的常迭代器(const_iterator) 
cend    返回指向容器末尾位置的常迭代器 
=================Capacity================ 
size     返回有效元素个数 
max_size  返回 unordered_map 支持的最大元素个数 
empty        判断是否为空 
=================元素访问================= 
operator[]       访问元素 
at         访问元素 
=================元素修改================= 
insert    插入元素 
erase   删除元素 
swap    交换内容 
clear     清空内容 
emplace  构造及插入一个元素 
emplace_hint 按提示构造及插入一个元素 
================操作========================= 
find       通过给定主键查找元素,没找到:返回unordered_map::end
count      返回匹配给定主键的元素的个数 
equal_range   返回值匹配给定搜索值的元素组成的范围 
================Buckets====================== 
bucket_count    返回槽(Bucket)数 
max_bucket_count    返回最大槽数 
bucket_size       返回槽大小 
bucket       返回元素所在槽的序号 
load_factor     返回载入因子,即一个元素槽(Bucket)的最大元素数 
max_load_factor    返回或设置最大载入因子 
rehash       设置槽数 
reserve        请求改变容器容量

 插入元素示例:

复制代码
1 // unordered_map::insert 2 #include <iostream> 3 #include <string> 4 #include <unordered_map> 5 using namespace std; 6 7 void display(unordered_map<string,double> myrecipe,string str) 8 { 9 cout << str << endl; 10 for (auto& x: myrecipe) 11 cout << x.first << ": " << x.second << endl; 12 cout << endl; 13 } 14 15 int main () 16 { 17 unordered_map<string,double> 18 myrecipe, 19 mypantry = {{"milk",2.0},{"flour",1.5}}; 20 21 /****************插入*****************/ 22 pair<string,double> myshopping ("baking powder",0.3); 23 myrecipe.insert (myshopping); // 复制插入 24 myrecipe.insert (make_pair<string,double>("eggs",6.0)); // 移动插入 25 myrecipe.insert (mypantry.begin(), mypantry.end()); // 范围插入 26 myrecipe.insert ({{"sugar",0.8},{"salt",0.1}}); // 初始化数组插入(可以用二维一次插入多个元素,也可以用一维插入一个元素) 27 myrecipe["coffee"] = 10.0; //数组形式插入 28 29 display(myrecipe,"myrecipe contains:"); 30 31 /****************查找*****************/ 32 unordered_map<string,double>::const_iterator got = myrecipe.find ("coffee"); 33 34 if ( got == myrecipe.end() ) 35 cout << "not found"; 36 else 37 cout << "found "<<got->first << " is " << got->second<<"\n\n"; 38 /****************修改*****************/ 39 myrecipe.at("coffee") = 9.0; 40 myrecipe["milk"] = 3.0; 41 display(myrecipe,"After modify myrecipe contains:"); 42 43 44 /****************擦除*****************/ 45 myrecipe.erase(myrecipe.begin()); //通过位置 46 myrecipe.erase("milk"); //通过key 47 display(myrecipe,"After erase myrecipe contains:"); 48 49 /****************交换*****************/ 50 myrecipe.swap(mypantry); 51 display(myrecipe,"After swap with mypantry, myrecipe contains:"); 52 53 /****************清空*****************/ 54 myrecipe.clear(); 55 display(myrecipe,"After clear, myrecipe contains:"); 56 return 0; 57 } 58 /* 59 myrecipe contains: 60 salt: 0.1 61 milk: 2 62 flour: 1.5 63 coffee: 10 64 eggs: 6 65 sugar: 0.8 66 baking powder: 0.3 67 68 found coffee is 10 69 70 After modify myrecipe contains: 71 salt: 0.1 72 milk: 3 73 flour: 1.5 74 coffee: 9 75 eggs: 6 76 sugar: 0.8 77 baking powder: 0.3 78 79 After erase myrecipe contains: 80 flour: 1.5 81 coffee: 9 82 eggs: 6 83 sugar: 0.8 84 baking powder: 0.3 85 86 After swap with mypantry, myrecipe contains: 87 flour: 1.5 88 milk: 2 89 90 After clear, myrecipe contains: 91 */
复制代码

遍历示例:

复制代码
1 // unordered_map::bucket_count 2 #include <iostream> 3 #include <string> 4 #include <unordered_map> 5 using namespace std; 6 7 int main () 8 { 9 unordered_map<string,string> mymap = 10 { 11 {"house","maison"}, 12 {"apple","pomme"}, 13 {"tree","arbre"}, 14 {"book","livre"}, 15 {"door","porte"}, 16 {"grapefruit","pamplemousse"} 17 }; 18 /************begin和end迭代器***************/ 19 cout << "mymap contains:"; 20 for ( auto it = mymap.begin(); it != mymap.end(); ++it ) 21 cout << " " << it->first << ":" << it->second; 22 cout << endl; 23 /************bucket操作***************/ 24 unsigned n = mymap.bucket_count(); 25 26 cout << "mymap has " << n << " buckets.\n"; 27 28 for (unsigned i=0; i<n; ++i) 29 { 30 cout << "bucket #" << i << "'s size:"<<mymap.bucket_size(i)<<" contains: "; 31 for (auto it = mymap.begin(i); it!=mymap.end(i); ++it) 32 cout << "[" << it->first << ":" << it->second << "] "; 33 cout << "\n"; 34 } 35 36 cout <<"\nkey:'apple' is in bucket #" << mymap.bucket("apple") <<endl; 37 cout <<"\nkey:'computer' is in bucket #" << mymap.bucket("computer") <<endl; 38 39 return 0; 40 } 41 /* 42 mymap contains: door:porte grapefruit:pamplemousse tree:arbre apple:pomme book:livre house:maison 43 mymap has 7 buckets. 44 bucket #0's size:2 contains: [book:livre] [house:maison] 45 bucket #1's size:0 contains: 46 bucket #2's size:0 contains: 47 bucket #3's size:2 contains: [grapefruit:pamplemousse] [tree:arbre] 48 bucket #4's size:0 contains: 49 bucket #5's size:1 contains: [apple:pomme] 50 bucket #6's size:1 contains: [door:porte] 51 52 key:'apple' is in bucket #5 53 54 key:'computer' is in bucket #6 55 */
复制代码

 


__EOF__

本文作者朤尧
本文链接https://www.cnblogs.com/langyao/p/8823092.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   朤尧  阅读(134873)  评论(3编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示