您好,登录后才能下订单哦!
这篇文章主要介绍了C++中map字典怎么用,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。
若想在 C++ 中使用 map 类型创建字典,则需要包含 map 头文件,如下:
#include <map>
map 类型的定义如下:
map<KeyType, ValueType> dict;
其中,KeyType 代表键的数据类型,ValueType 代表值的数据类型。KeyType 默认是 const 类型,即键在确认之后为只读数据。另外,在一个 map 数据中,一个键只能出现一次;而在 multimap 类型数据中,一个键可以出现多次,本次主要讨论 map 数据。看下面一个例子:
#include <iostream> #include <string> #include <map> using namespace std; int main(void) { map<string, int> dict{{"key1", 2}}; // 定义一个 map 类型数据 dict["key2"] = 3; // 创建并赋值 dict["key3"] ; cout << "length of dict: " << dict.size() << endl; // 长度 cout << dict["key1"] << endl; // 查找 cout << dict["key2"] << endl; cout << dict["key3"] << endl; // 值默认为0 } //======= 运行结果如下 ========// length of dict: 2 2 3 0
例子中首先声明了一个 map 类型数据 dict ,key 的数据类型为 string ,value 的数据类型为 int。初始化时注意一对键值对要放在一对花括号{}中,并用逗号隔开:
{key, value}
如果键 key 对还未出现在 dict 中,下标运算会创建一个新元素,其值默认为 0 。这里创建了三个键值对,一个key 为 字符串 "key1" ,值为 2;key 为 字符串 "key3" 的键值对由于未被赋值,因此其值默认为 0 。
上述 dict 字典中存储的每一个数据都是 pair 类型的数据,即 map 数据是一群 pair 类型的集合。一个 pair 保存两数据成员: first 和 second,分别用来存储一个键值对的 键 和 值 ,其中 first 成员是 const 的,这也解释了上面提到的 键在确认之后为只读数据。pair 的标准库类型定义在头文件 utility 中,在定义一个 pair 时,其默认构造函数会对数据成员进行初始化。一个例子如下:
int main(void) { pair<string, int> a_pair{"key", 1}; // 定义一个 pair 并初始化 cout << a_pair.first << ": " << a_pair.second << endl; } // =========== 运行结果 =========== // key: 1
map 数据的遍历主要有两种方法,一个是直接遍历,另一种是使用迭代器的遍历。
#include <iostream> #include <string> #include <map> using namespace std; int main(void) { map<string, int> dict; // 定义一个 map 类型数据 dict["key1"] = 2; // 创建并赋值 dict["key2"] = 3; // dict["key3"] ; // 默认值为0 for(auto c : dict) // 遍历,c++11 特有循环方式 { cout << c.first << ": " << c.second << endl; } } //============ 运行结果 ============// key1: 2 key2: 3 key3: 0
这种遍历方式就是 for 循环直接遍历。每次循环都会从 dict 中提取一个 pair 类型的对象存入 c 中以供后续操作。
map 支持 vector 中的 begin、end、cbegin、cend 操作,因此我们可以使用这些函数获取迭代器,然后使用迭代器来遍历 map。begin、end 指向首元素以及尾元素之后位置(one past the last element)的迭代器,而容器中的元素位于 begin 与 end 之间,不包含 end,即是一个左闭右开的区间:[begin,end)。cbegin、cend 是C++11引入的新标准,返回 const_iterator,只能用来读取迭代器所指向内容的数据,不能修改数据 。一个使用迭代器遍历的例子如下:
#include <iostream> #include <string> #include <map> using namespace std; int main(void) { // 定义并初始化一个 map 类型数据 map<string, int> dict{{"key1", 1}, {"key2", 2}, {"key3", 3}}; auto map_it = dict.begin(); // 获取指向首元素的迭代器 // 判断范围,比较当前迭代器和尾后元素迭代器 while (map_it != dict.end()) { cout << map_it->first << ": " << map_it->second << endl; map_it++; // 迭代器递增,移动到下一个元素 } }
map 的 insert 成员函数用来添加一个元素或者一个元素范围,emplace 成员函数用来添加单个元素。使用 insert 方法向 map 中添加元素的方法如下,不过常用的方式就是第一种方式,剩下的仨了解下就行。
dict.insert({"key", 1}) // 或者 dict.emplace({"key", 1}) dict.insert(make_pair("key", 1)) dict.insert(pair<string, int>("key", 1)) dict.insert(map<string, int>::value_type("key", 1))
另外对于一个不存在的键的单一元素的 insert 或者 emplace 的插入操作会返回一个 pair ,告诉我们是否添加成功,该 pair 的 first 成员是一个迭代器,指向具有给定关键字的元素,second 成员是一个 bool 值,指出元素是插入成功还是已存在于 dict 中,如果之前不存在,则返回true;如果先前已存在,则值为 false。
int main(void) { map<string, int> dict{{"key1", 1}}; // 定义一个 map auto ret1 = dict.insert({"key2", 1}); // 执行插入操作,若 "key"不存在于dict中,则返回 cout << "attention: ret1.first is a iterator points the element we insert" << endl; cout << ret1.first->first << ":" << ret1.first->second << endl; cout << "key2 insert successfully? " << ret1.second << endl; auto ret2 = dict.insert({"key1", 3}); // "key"已存在于dict中,则insert什么也不做 cout << "attention: ret2.first is a iterator points the element we insert" << endl; cout << ret2.first->first << ":" << ret2.first->second << endl; cout << "key1 insert successfully? " << ret2.second << endl; } //========= 运行结果 ==========// attention: ret1.first is a iterator points the element we insert key2:1 key2 insert successfully? 1 attention: ret2.first is a iterator points the element we insert key1:1 key1 insert successfully? 0
例子中的返回值 pair 的完整类型如下:
pair<map<string, int>::iterator, bool>
但是!上面的 insert 方式还是麻烦了点,不如直接使用文章开头说的下标操作!如果键 key 对还未出现在 dict 中,下标运算会创建一个新元素,其值默认为 0 。
当插入一个元素范围时,可以做如下操作,这时没有返回值。
dict.insert(dict2.begin(), dict2.end());
map 有三个版本的 erase 操作,分别如下:
从 dict 中删除 键 为 key 的元素,返回删除元素的数量,对于 map 类型来说为 1。
从 dict 中删除迭代器 p 指定的元素。p 必须指向 dict 中一个真实元素且不能等于 dict.end()。返回一个指向 p 之后的元素的迭代器。
从 dict 中删除迭代器 b 和 e 之间的元素,返回e。
int main(void) { // 定义并初始化一个 map 类型数据 map<string, int> dict{{"key1", 1}, {"key2", 2}, {"key3", 3}, {"key4", 4}, {"key5", 5}}; int ret1 = dict.erase("key1"); // 删除键为 "key1" 的元素 cout << "ret1: " << ret1 << endl; auto ret2 = dict.erase(dict.begin()); // 使用迭代器 cout << "(ret2->first:ret2->second) = " << ret2->first << ":" << ret2->second << endl; auto ret3 = dict.erase(dict.begin(), dict.end()); // 清空 cout << "ret3->first: " << ret3->first << endl; } //=========== 运行结果 ============// ret1: 1 (ret2->first:ret2->second) = key3:3 ret3->first:
map 提供了一些查找元素的操作如下:
1、dict.find(key) // 返回一个迭代器 ,指向第一个键为 key 的元素,若 key 不存在于 dict 中,则返回 dict.end() 2、dict.count(key) // 返回键为 key 的元素的数量,对于 map 来说,返回1 3、dict.lower_bound(key) // 返回一个迭代器,指向第一个键不小于 key 的元素 4、dict.upper_bound(key) // 返回一个迭代器,指向第一个键大于 key 的元素 5、dict.equal_range(key) // 返回一个迭代器pair,表示关键字恩于 key 的元素的范围。如果不存在,则pair的两个成员均为 //dict.end()
一般来说,2~5的方法多用于 multimap 类型的数据中。如果只是想查询一个元素是否存在于 dict 中,则使用 find 是最好的选择。
另外需要注意的是,如果使用下标操作访问元素,如果该元素并不存在于 dict 中,则该操作会创建一个元素,因此,使用什么样的访问方式需要根据我们的使用环境进行选择。
map 是基于树的结构的,并且内部元素是有序的,即是经过键排序的:如果键的类型是数字,则按照数字大小进行排序,如果是 string,则按照字典序进行排序。
感谢你能够认真阅读完这篇文章,希望小编分享的“C++中map字典怎么用”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。