C++中map 字典的基本使用教程

目录
  • 前言
  • 1、map 类型的声明
  • 2、pair 类型
  • 3、map 数据的遍历
    • 1)直接遍历:
    • 2)使用迭代器遍历
  • 4、添加元素
  • 5、删除元素
    • 1、dict.erase(key)
    • 2、dict.erase(p)
    • 3、dict.erase(b, e)
  • 6、访问元素
  • 7、其他细节
  • 总结

前言

在 C++ 中,map 是关联容器的一种,关联容器将值与键关联到一起,并使用键来查找值。这与 python 中的字典类型类似,也是用来存储键-值对(key-value) 形式的数据的,其同样具有遍历、插入、查询、删除等功能,下面将一一介绍。

1、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 。

2、pair 类型

上述 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

3、map 数据的遍历

map 数据的遍历主要有两种方法,一个是直接遍历,另一种是使用迭代器的遍历。

1)直接遍历:

#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 中以供后续操作。

2)使用迭代器遍历

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++;  // 迭代器递增,移动到下一个元素
    }
}

4、添加元素

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());

5、删除元素

map 有三个版本的 erase 操作,分别如下:

1、dict.erase(key)

从 dict 中删除 键 为 key 的元素,返回删除元素的数量,对于 map 类型来说为 1。

2、dict.erase(p)

从 dict 中删除迭代器 p 指定的元素。p 必须指向 dict 中一个真实元素且不能等于 dict.end()。返回一个指向 p 之后的元素的迭代器。

3、dict.erase(b, e)

从 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:

6、访问元素

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 中,则该操作会创建一个元素,因此,使用什么样的访问方式需要根据我们的使用环境进行选择。

7、其他细节

map 是基于树的结构的,并且内部元素是有序的,即是经过键排序的:如果键的类型是数字,则按照数字大小进行排序,如果是 string,则按照字典序进行排序。

总结

到此这篇关于C++中map、字典的基本使用的文章就介绍到这了,更多相关C++ map字典使用内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • c++容器list、vector、map、set区别与用法详解

    c++容器list.vector.map.set区别 list 封装链表,以链表形式实现,不支持[]运算符. 对随机访问的速度很慢(需要遍历整个链表),插入数据很快(不需要拷贝和移动数据,只需改变指针的指向). 新添加的元素,list可以任意加入. vector 封装数组,使用连续内存存储,支持[]运算符. 对随机访问的速度很快,对头插元素速度很慢,尾插元素速度很快 新添加的元素,vector有一套算法. map 采用平衡检索二叉树:红黑树 存储结构为键值对<key,value> set 采用

  • c++中map的基本用法和嵌套用法实例分析

    本文实例讲述了c++中map的基本用法和嵌套用法.分享给大家供大家参考.具体分析如下: C++中map容器提供一个键值对容器,map与multimap差别仅仅在于multiple允许一个键对应多个值.本文主要总结一下map基本用法和嵌套用法示例. 一.map基本用法 1. 头文件 复制代码 代码如下: #include <map> 2. 定义 复制代码 代码如下: map<int,int> my_Map; //注意这里的int和int可以是其他类型 或者是 复制代码 代码如下: t

  • C++ map用法总结(整理)

    1,map简介 map是STL的一个关联容器,它提供一对一的hash. 第一个可以称为关键字(key),每个关键字只能在map中出现一次:第二个可能称为该关键字的值(value): map以模板(泛型)方式实现,可以存储任意类型的数据,包括使用者自定义的数据类型.Map主要用于资料一对一映射(one-to-one)的情況,map內部的实现自建一颗红黑树,这颗树具有对数据自动排序的功能.在map内部所有的数据都是有序的,后边我们会见识到有序的好处.比如一个班级中,每个学生的学号跟他的姓名就存在著一

  • C++中 map的基本操作

    1.map简介 map是一类关联式容器.它的特点是增加和删除节点对迭代器的影响很小,除了那个操作节点,对其他的节点都没有什么影响.对于迭代器来说,可以修改实值,而不能修改key. 2.map的功能 自动建立Key - value的对应.key 和 value可以是任意你需要的类型. 根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次. 快速插入Key - Value 记录. 快速删除记录 根据Key 修改val

  • C++中vector和map的删除方法(推荐)

    1.连续内存序列容器(vector,string,deque) 序列容器的erase方法返回值是指向紧接在被删除元素之后的元素的有效迭代器,可以根据这个返回值来安全删除元素. vector<int> c; for(vector<int>::iterator it = c.begin(); it != c.end();) { if(need_delete()) it = c.erase(it); else ++it; } 2.关联容器(set,multiset,map,multima

  • c++ map,mutimap删除问题分析

    这样删除会导致程序内存覆盖等一系列不可预知的bug 复制代码 代码如下: map<string, string>::iterator iter; for ( iter = mm.begin();iter != mm.end(); iter ++ ) { if ( iter->second == something ) { mm.erase( iter ); } } 原因:当erase掉iter后,继续执行iter++,这个时候就乱套了 正确方法: 复制代码 代码如下: for (iter

  • 深入了解C++中map用法

    /************************************************************************ * * Map的特点: 1.存储Key-value对 * 2.支持快速查找,查找的复杂度基本是Log(N) * 3.快速插入,快速删除,快速修改记 * /************************************************************************/ #include <iostream> #inc

  • C++中map 字典的基本使用教程

    目录 前言 1.map 类型的声明 2.pair 类型 3.map 数据的遍历 1)直接遍历: 2)使用迭代器遍历 4.添加元素 5.删除元素 1.dict.erase(key) 2.dict.erase(p) 3.dict.erase(b, e) 6.访问元素 7.其他细节 总结 前言 在 C++ 中,map 是关联容器的一种,关联容器将值与键关联到一起,并使用键来查找值.这与 python 中的字典类型类似,也是用来存储键-值对(key-value) 形式的数据的,其同样具有遍历.插入.查询

  • java中Map、Set、List的简单使用教程(快速入门)

    Map.Set.List List的常用方法 1.创建 List<Integer> list = new ArrayList<>(); List<Integer> list = new LinkedList<>(); //同时可以作为链表用 List<List<Integer>> list = new ArrayList<>(); 2.遍历 //本质上其实是调用Iterator for(String s:list){ Sy

  • python中format()函数的简单使用教程

    先给大家介绍下python中format函数,在文章下面给大家介绍python.format()函数的简单使用 ---恢复内容开始--- python中format函数用于字符串的格式化 通过关键字 print('{名字}今天{动作}'.format(名字='陈某某',动作='拍视频'))#通过关键字 grade = {'name' : '陈某某', 'fenshu': '59'} print('{name}电工考了{fenshu}'.format(**grade))#通过关键字,可用字典当关键

  • Flutter中嵌入Android 原生TextView实例教程

    前言 本篇文章 中写到的是 flutter 调用了Android 原生的 TextView 案例 添加原生组件的流程基本上可以描述为: 1 android 端实现原生组件PlatformView提供原生view 2 android 端创建PlatformViewFactory用于生成PlatformView 3 android 端创建FlutterPlugin用于注册原生组件 4 flutter 平台嵌入 原生view 1 创建原生组件 创建在fLutter工程时会生成几个文件夹,lib是放fl

  • Python中random模块常用方法的使用教程

    前言 Python 的random模块包含许多随机数生成器. random是Python标准库之一,直接导入即可使用.本文介绍random中常用方法的用法. 一.生成随机的整数 # coding=utf-8 import random print(random.randint(1, 5)) print(random.randrange(0, 51, 5)) 运行结果: 3 40 randint(start, end)会返回一个start到end之间的整数,这里是左闭右闭区间.也就是说可能会返回e

  • 在Docker中安装Elasticsearch7.6.2的教程

    安装docker 你要安装完成docker,不再说明了. 安装Elasticsearch 注意:使用版本为 7.6.2,你可以选择其他版本 拉取镜像 docker pull elasticsearch:7.6.2 启动容器 docker run --restart=always -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" \ -e ES_JAVA_OPTS="-Xms512m -Xmx512m"

  • python中spy++的使用超详细教程

    1.spy++的基本操作 我们下载spy++: Microsoft Spy++ V15.0.26724.1 简体中文绿色版 64位 1.1 窗口属性查找 拖住中间的"寻找工具"放到想要定位的软件上,然后松开 以微信为例,我们会得到"微信"这个窗口的句柄,为"00031510",注意这个句柄是"十六进制",即"0x31510". 点击ok我们会看到更详细的属性信息 1.2 窗口spy++定位 同理拖放到&qu

  • 详解Flutter中视频播放器插件的使用教程

    目录 创建一个新的视频播放器 添加播放和暂停按钮 创建一个快进 添加一个视频进度指示器 应用视频的字幕 结论 您已经看到很多包含视频内容的应用程序,比如带有视频教程的食谱应用程序.电影应用程序和体育相关的应用程序.您是否想知道如何将视频内容添加到您的下一个Flutter应用程序中? 从头开始实现视频功能将是一项繁重的任务.但有几个插件可以让开发者的生活变得轻松.视频播放器插件是可用于 Flutter 的最佳插件之一,可满足这一要求. 在这篇文章中,您将学习如何应用视频播放器插件以及控制视频播放器

  • C++中map和set的简介及使用详解

    目录 关联式容器 键值对 set set的介绍 set的使用 multiset map map的介绍 map的使用 map构造 map的插入 map的[]运算符重载 multiset 关联式容器 关联式容器包括序列式容器和关联式容器 序列式容器: 底层为线性序列的数据结构,里面存储的是元素本身,包含vector.list.deque.forward_list(C++11)等.关联式容器: 里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高,包含set.map.u

  • JavaScript中Map与Object应用场景

    目录 引言 为什么 Object 缺少哈希映射 不需要的继承 名称冲突 尺寸 迭代 清除 检查属性是否存在 哈希映射的映射 性能 基准测试实施细节 字符串键 整数键 数字键 内存使用情况 结论 浏览器兼容性注意事项 引言 在 JavaScript 中选择 Object 和 Map 的缺失指南 在 JavaScript 中,对象很方便.它们使我们能够轻松地将多条数据组合在一起.在 ES6 之后,我们为该语言添加了一个新功能 - Map. 在很多方面,它似乎比Object更强大,但界面有点笨拙.然而

随机推荐