关联容器:unordered_map详细介绍(附可运行代码)
来源:互联网 发布:ubuntu 打开u盘 编辑:程序博客网 时间:2024/06/05 13:25
- 介绍
- 1 特性
- 2 Hashtable和bucket
- 模版
- 1 迭代器
- 功能函数
- 1 构造函数
- 12示例代码
- 2 容量操作
- 21 size
- 22 empty
- 3 元素操作
- 31 find
- 32 insert
- 33 at
- 34 erase
- 35 clear
- 36 swap
- 37 示例代码
- 4 迭代器和bucket操作
- 41 begin
- 42 end
- 43 bucket
- 44 bucket_count
- 45 bucket_size
- 46 示例代码
- 1 构造函数
- 最后
- 介绍
1.介绍
最近使用到一个c++的容器——unordered_map,它是一个关联容器,内部采用的是hash表结构,拥有快速检索的功能。
1.1 特性
- 关联性:通过key去检索value,而不是通过绝对地址(和顺序容器不同)
- 无序性:使用hash表存储,内部无序
- Map : 每个值对应一个键值
- 键唯一性:不存在两个元素的键一样
- 动态内存管理:使用内存管理模型来动态管理所需要的内存空间
1.2 Hashtable和bucket
由于unordered_map内部采用的hashtable的数据结构存储,所以,每个特定的key会通过一些特定的哈希运算映射到一个特定的位置,我们知道,hashtable是可能存在冲突的(多个key通过计算映射到同一个位置),在同一个位置的元素会按顺序链在后面。所以把这个位置称为一个bucket是十分形象的(像桶子一样,可以装多个元素)。可以参考这篇介绍哈希表的文章
所以unordered_map内部其实是由很多哈希桶组成的,每个哈希桶中可能没有元素,也可能有多个元素。
2. 模版
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;
主要使用的也是模板的前2个参数<键,值>(需要更多的介绍可以点击这里)
unordered_map<const Key, T> map;
2.1 迭代器
unordered_map的迭代器是一个指针,指向这个元素,通过迭代器来取得它的值。
unordered_map<Key,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>)
它的键值分别是迭代器的first和second属性。
it->first; // same as (*it).first (the key value)it->second; // same as (*it).second (the mapped value)
3. 功能函数
3.1 构造函数
unordered_map的构造方式有几种:
- 构造空的容器
- 复制构造
- 范围构造
- 用数组构造
3.1.2示例代码
// constructing unordered_maps#include <iostream>#include <string>#include <unordered_map>using namespace std;typedef unordered_map<string,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"}} ); // 用数组初始 stringmap fourth (second); // 复制初始化 stringmap fifth (merge(third,fourth)); // 移动初始化 stringmap sixth (fifth.begin(),fifth.end()); // 范围初始化 cout << "sixth contains:"; for (auto& x: sixth) cout << " " << x.first << ":" << x.second; cout << endl; return 0;}
输出结果:
sixth contains: apple:red lemon:yellow orange:orange strawberry:red
3.2 容量操作
3.2.1 size
size_type size() const noexcept;
返回unordered_map的大小
3.2.2 empty
bool empty() const noexcept;
- 为空返回true
- 不为空返回false,和用size() == 0判断一样。
3.3 元素操作
3.3.1 find
iterator find ( const key_type& k );
查找key所在的元素。
- 找到:返回元素的迭代器。通过迭代器的second属性获取值
- 没找到:返回unordered_map::end
3.3.2 insert
插入有几种方式:
- 复制插入(复制一个已有的pair的内容)
- 数组插入(直接插入一个二维数组)
- 范围插入(复制一个起始迭代器和终止迭代器中间的内容)
- 数组访问模式插入(和数组的[]操作很相似)
具体的例子可以看后面示例代码。
3.3.3 at
mapped_type& at ( const key_type& k );
查找key所对应的值
- 如果存在:返回key对应的值,可以直接修改,和[]操作一样。
- 如果不存在:抛出 out_of_range 异常.
mymap.at(“Mars”) = 3396; //mymap[“Mars”] = 3396
3.3.4 erase
擦除元素也有几种方式:
通过位置(迭代器)
iterator erase ( const_iterator position );
通过key
size_type erase ( const key_type& k );
通过范围(两个迭代器)
iterator erase ( const_iterator first, const_iterator last );
3.3.5 clear
void clear() noexcept
清空unordered_map
3.3.6 swap
void swap ( unordered_map& ump );
交换两个unordered_map(注意,不是交换特定元素,是整个交换两个map中的所有元素)
3.3.7 示例代码
// unordered_map::insert#include <iostream>#include <string>#include <unordered_map>using namespace std;void display(unordered_map<string,double> myrecipe,string str){ cout << str << endl; for (auto& x: myrecipe) cout << x.first << ": " << x.second << endl; cout << endl;}int main (){ unordered_map<string,double> myrecipe, mypantry = {{"milk",2.0},{"flour",1.5}}; /****************插入*****************/ pair<string,double> myshopping ("baking powder",0.3); myrecipe.insert (myshopping); // 复制插入 myrecipe.insert (make_pair<string,double>("eggs",6.0)); // 移动插入 myrecipe.insert (mypantry.begin(), mypantry.end()); // 范围插入 myrecipe.insert ({{"sugar",0.8},{"salt",0.1}}); // 初始化数组插入(可以用二维一次插入多个元素,也可以用一维插入一个元素) myrecipe["coffee"] = 10.0; //数组形式插入 display(myrecipe,"myrecipe contains:"); /****************查找*****************/ unordered_map<string,double>::const_iterator got = myrecipe.find ("coffee"); if ( got == myrecipe.end() ) cout << "not found"; else cout << "found "<<got->first << " is " << got->second<<"\n\n"; /****************修改*****************/ myrecipe.at("coffee") = 9.0; myrecipe["milk"] = 3.0; display(myrecipe,"After modify myrecipe contains:"); /****************擦除*****************/ myrecipe.erase(myrecipe.begin()); //通过位置 myrecipe.erase("milk"); //通过key display(myrecipe,"After erase myrecipe contains:"); /****************交换*****************/ myrecipe.swap(mypantry); display(myrecipe,"After swap with mypantry, myrecipe contains:"); /****************清空*****************/ myrecipe.clear(); display(myrecipe,"After clear, myrecipe contains:"); return 0;}
输出结果:
myrecipe contains:salt: 0.1milk: 2flour: 1.5coffee: 10eggs: 6sugar: 0.8baking powder: 0.3found coffee is 10After modify myrecipe contains:salt: 0.1milk: 3flour: 1.5coffee: 9eggs: 6sugar: 0.8baking powder: 0.3After erase myrecipe contains:flour: 1.5coffee: 9eggs: 6sugar: 0.8baking powder: 0.3After swap with mypantry, myrecipe contains:flour: 1.5milk: 2After clear, myrecipe contains:
3.4 迭代器和bucket操作
3.4.1 begin
iterator begin() noexcept; local_iterator begin ( size_type n );
- begin() : 返回开始的迭代器(和你的输入顺序没关系,因为它的无序的)
- begin(int n) : 返回n号bucket的第一个迭代器
3.4.2 end
iterator end() noexcept; local_iterator end( size_type n );
- end(): 返回结束位置的迭代器
- end(int n) : 返回n号bucket的最后一个迭代器
3.4.3 bucket
size_type bucket ( const key_type& k ) const;
返回通过哈希计算key所在的bucket(注意:这里仅仅做哈希计算确定bucket,并不保证key一定存在bucket中!)
3.4.4 bucket_count
size_type bucket_count() const noexcept;
返回bucket的总数
3.4.5 bucket_size
size_type bucket_size ( size_type n ) const;
返回第i个bucket的大小(这个位置的桶子里有几个元素,注意:函数不会判断n是否在count范围内)
3.4.6 示例代码
// unordered_map::bucket_count#include <iostream>#include <string>#include <unordered_map>using namespace std;int main (){ unordered_map<string,string> mymap = { {"house","maison"}, {"apple","pomme"}, {"tree","arbre"}, {"book","livre"}, {"door","porte"}, {"grapefruit","pamplemousse"} }; /************begin和end迭代器***************/ cout << "mymap contains:"; for ( auto it = mymap.begin(); it != mymap.end(); ++it ) cout << " " << it->first << ":" << it->second; cout << endl; /************bucket操作***************/ unsigned n = mymap.bucket_count(); cout << "mymap has " << n << " buckets.\n"; for (unsigned i=0; i<n; ++i) { cout << "bucket #" << i << "'s size:"<<mymap.bucket_size(i)<<" contains: "; for (auto it = mymap.begin(i); it!=mymap.end(i); ++it) cout << "[" << it->first << ":" << it->second << "] "; cout << "\n"; } cout <<"\nkey:'apple' is in bucket #" << mymap.bucket("apple") <<endl; cout <<"\nkey:'computer' is in bucket #" << mymap.bucket("computer") <<endl; return 0;}
输出结果:
mymap contains: door:porte grapefruit:pamplemousse tree:arbre apple:pomme book:livre house:maisonmymap has 7 buckets.bucket #0's size:2 contains: [book:livre] [house:maison]bucket #1's size:0 contains:bucket #2's size:0 contains:bucket #3's size:2 contains: [grapefruit:pamplemousse] [tree:arbre]bucket #4's size:0 contains:bucket #5's size:1 contains: [apple:pomme]bucket #6's size:1 contains: [door:porte]key:'apple' is in bucket #5key:'computer' is in bucket #6
最后
unordered_map常用的功能函数介绍就这么多了,还有一些比较不常用的功能的介绍,可以参考这里
- 关联容器:unordered_map详细介绍(附可运行代码)
- 关联容器(五):unordered_map
- C++ 关联容器详细介绍
- 关联容器(map、set、multimap、multiset、pair、unordered_map)
- C++关联容器(unordered_map,vector,unordered_set)
- 【Leetcode】 1.two sum unordered_map 关联容器
- 分水岭算法的详细介绍(附c代码)
- SpringMvc常用注解详细介绍(附示例代码)
- sprintf 和 sscanf 详细解读(有可运行代码)
- 热核特征(heat kernel signature,HKS)简单解释(附可运行代码)
- 从控制台读入double数据的容错处理(附完整可运行代码)
- 平衡二叉树(AVL)的实现,附可运行C语言代码
- SnmpTrap 线程 内附代码,eclipse可正常运行测试!
- ContentProvider详细介绍(附实例源码)
- ContentProvider详细介绍(附实例源码)
- C++中一些常用的容器的方法小结(附详细代码及详细注释)
- java 大数取模(有可运行代码和详细注解)
- Objective-C文件组织介绍(附代码)
- java数组和list互转方法
- JavaSe基础(19)-- String 与 StringBuffer
- System V消息队列
- 三、Java学习之语言基础(2)
- 在安装Ubuntu的POWER服务器上,开启SMT
- 关联容器:unordered_map详细介绍(附可运行代码)
- 【Android】笔记本
- JavaSe基础(20)-- 时间日期类
- enable-assembler,--enable-static,--enable-shared编译项的研究 .
- [HDU2588]GCD(数论)
- ffmpeg中的时间单位
- javascript中的字符串函数
- shiro jsp标签使用
- C# this 关键字