C++系列-STL容器中的map容器

2024-09-04 17:04
文章标签 c++ 系列 容器 map stl

本文主要是介绍C++系列-STL容器中的map容器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

STL容器中的map容器

  • map的基本概念
  • map的特点
  • map的构造
  • map的赋值
  • map的插入
  • map的删除
  • map的大小
  • map的交换查找,统计
  • map的排序


无题二首·其一 李商隐
昨夜星辰昨夜风,画楼西畔桂堂东。
身无彩凤双飞翼,心有灵犀一点通。
隔座送钩春酒暖,分曹射覆蜡灯红。
嗟余听鼓应官去,走马兰台类转蓬。


map的基本概念

  • map是一种关联容器,也被称为字典,底层结构是二叉树。
  • 它以键值对key,value的形式存储元素。其中key是唯一的,用于快速查找对应的value。
  • 如果尝试插入具有相同key的元素,旧的值将被新的覆盖。
  • map提供双向迭代器,可以遍历容器中的所有键值对。
  • 迭代器指向的是pair类型的对象,first成员属性是key,second成员属性是value
  • multimap的key值是可以重复的,其它的与map类似。

map的特点

  • 有序性,map中的元素是按照key的特定顺序存储的,默认情况下是key的升序排列,可以按照顺序遍历map中的元素,并可以进行范围查询等操作。
  • map中的key有唯一性,multimap则无。
  • 高效的查找和插入。
  • map以键值对的方式存储元素,方便将相关的数据关联在一起。
  • 可以通过自定义的比较函数来改变key的排序规则。

map的构造

构造函数描述
map<type1, type2> mp1默认构造函数
map<type1, type2> mp2(mp1)拷贝构造
map<type1, type2> mp2{{},{}…}初始化列表构造
map<type1, type2> mp4(迭代器1, 迭代器2范围构造
map<type1, type2> mp5(move(mp1)直接移动,并不拷贝
code:
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;template<typename T1, typename T2>
void print_map(const map<T1, T2>& mp)
{for (auto i_mp: mp){cout << "first: " << i_mp.first << ", second: " << i_mp.second << endl;}
}
void test01()
{// 默认构造map<string, int> mp1;pair<string, int> pr1 ("Lily", 9);pair<string, int> pr2 ("Lucy", 10);mp1.insert(pr1);mp1.insert(pr2);cout << "---------- mp1, mp1.size() ---------- " << mp1.size() << endl;print_map(mp1);cout << "value of key Lily: " << mp1["Lily"] << endl;	// 访问元素value的方式// 拷贝构造map<string, int> mp2(mp1);cout << "---------- map<string, int> mp2(mp1), mp2 ---------- " << mp2.size() << endl;print_map(mp2);// 初始化列表构造map<string, int> mp3{ {"Hanmeimei", 9}, { "Poly", 2 } }) cout << "---------- map<string, int> mp3({{},{},...}), mp3 ---------- " << mp3.size() << endl;print_map(mp3);// 范围构造vector<pair<string, int>> vec1 = { {"张三", 5}, {"李四", 6}, {"王五", 7} };map<string, int> mp4(vec1.begin(), vec1.begin() + 2);cout << "---------- map<string, int> mp4(vec1.begin(), vec1.begin() + 2), mp4 ---------- " << mp4.size() << endl;print_map(mp4);// 移动构造,move括号中的元素空间会直接移动cout << "---------- 移动构造前 ----------" << endl;cout << "mp3.size(): " << mp3.size() << endl;map<string, int> mp5(move(mp3));cout << "---------- 移动构造后 ----------" << endl;cout << "---------- map<string, int> mp5(move(mp3)) ---------- " << mp5.size() << endl;print_map(mp5);cout << "mp3.size(): " << mp3.size() << endl;print_map(mp3);
}
int main()
{test01();system("pause");return 0;
}result:
---------- mp1, mp1.size() ---------- 2
first: Lily, second: 9
first: Lucy, second: 10
value of key Lily: 9
---------- map<string, int> mp2(mp1), mp2 ---------- 2
first: Lily, second: 9
first: Lucy, second: 10
---------- map<string, int> mp3({{},{},...}), mp3 ---------- 2
first: Hanmeimei, second: 9
first: Poly, second: 2
---------- map<string, int> mp4(vec1.begin(), vec1.begin() + 2), mp4 ---------- 2
first: 李四, second: 6
first: 张三, second: 5
---------- 移动构造前 ----------
mp3.size(): 2
---------- 移动构造后 ----------
---------- map<string, int> mp5(move(mp3)) ---------- 2
first: Hanmeimei, second: 9
first: Poly, second: 2
mp3.size(): 0

map的赋值

  • 使用=重载
code:
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;template<typename T1, typename T2>
void print_map(const map<T1, T2>& mp)
{for (auto i_mp : mp){cout << "first: " << i_mp.first << ", second: " << i_mp.second << endl;}
}
void test01()
{// = 赋值map<string, int> mp1{{"Lily", 9}, { "Lucy", 10 }};cout << "---------- mp1, mp1.size() ---------- " << mp1.size() << endl;print_map(mp1);map<string, int> mp2 = mp1;cout << "---------- map<string, int> mp2 = mp1, mp2 ---------- " << mp2.size() << endl;print_map(mp2);
}
int main()
{test01();system("pause");return 0;
}result:
---------- mp1, mp1.size() ---------- 2
first: Lily, second: 9
first: Lucy, second: 10
---------- map<string, int> mp2 = mp1, mp2 ---------- 2
first: Lily, second: 9
first: Lucy, second: 10

map的插入

构造函数描述
pair<iterator, bool> insert(pair<type ,type2>(key, value))insert插入pair,返回值是pair,第一个元素时迭代器,迭代器所指值的第一个元素是key,第二个是value,pair中的second元素bool类型表示是否插入成功
pair<iterator, bool> insert(make_pair(key, value))insert插入pair,pair由make_pair产生,返回值同上
pair<iterator, bool> insert(map<type1, type2>::value_type(key, value))使用type_value函数产生pair对象,返回值同上
mapped_type& mp1[value]=value[]插入法, 如果插错了,比如key写错了,会自动创建一个对应这个key的元素,value设置为0,建议少用,但[]通过key访问value很方便
void insert({ val1, val2, … })一次向 map 容器中插入多个键值对
void insert (InputIterator first, InputIterator last)插入某map容器中的指定区域
iterator insert (const_iterator position, const value_type& val)会按照key自动排序,不按照position的指示
code:
#include <iostream>
#include <map>
using namespace std;template<typename T1, typename T2>
void print_map(const map<T1, T2>& mp)
{for (auto i_mp : mp){cout << "first: " << i_mp.first << ", second: " << i_mp.second << endl;}
}
void test01()
{// pair<iterator, bool> insert(pair<type, type2>(key, value)map<string, int> mp1{{"Lily", 9}, { "Lucy", 10 }};//pair<map<string, int>::iterator, bool> pr1 = mp1.insert(pair<string, int>("Jim", 10));auto pr1 = mp1.insert(pair<string, int>("Jim", 10));	// 可以用auto,更简单cout << "----- pr1.first->first: " << pr1.first->first << ", pr1.first->second: " << pr1.first->second << ", pr1.second: " << pr1.second << endl;// pair<iterator, bool> insert(make_pair(key, value)auto pr2 = mp1.insert(make_pair("Poly", 2));cout << "----- pr2.first->first: " << pr2.first->first << ", pr2.first->second: " << pr2.first->second << ", pr2.second: " << pr2.second << endl;// iterator insert(map<type1, type2>::value_type(key, value))auto pr3 = mp1.insert(map<string, int>::value_type("Hanmeimei", 11));		// value_type返回是pair对象cout << "----- pr3.first->first: " << pr3.first->first << ", pr3.first->second: " << pr3.first->second << ", pr3.second: " << pr3.second << endl;// mapped_type& mp1[key]= valuemp1["MissGao"] = 33;// void insert({ val1, val2, ... });mp1.insert({ { "张三", 12 }, { "李四", 11 }, { "王五", 11 } });print_map(mp1);
}
int main()
{test01();system("pause");return 0;
}result:
----- pr1.first->first: Jim, pr1.first->second: 10, pr1.second: 1
----- pr2.first->first: Poly, pr2.first->second: 2, pr2.second: 1
----- pr3.first->first: Hanmeimei, pr3.first->second: 11, pr3.second: 1
first: Hanmeimei, second: 11
first: Jim, second: 10
first: Lily, second: 9
first: Lucy, second: 10
first: MissGao, second: 33
first: Poly, second: 2
first: 李四, second: 11
first: 王五, second: 11
first: 张三, second: 12

code:
#include <iostream>
#include <map>
using namespace std;template<typename T1, typename T2>
void print_map(const map<T1, T2>& mp)
{for (auto i_mp : mp){cout << "first: " << i_mp.first << ", second: " << i_mp.second << endl;}
}
void test01()
{cout << "---------- mp1 ----------" << endl;map<string, int> mp1{{"Lily", 9}, { "Lucy", 10 }};mp1.insert({ { "张三", 12 }, { "李四", 11 }, { "王五", 11 } });print_map(mp1);cout << "---------- mp2 ----------" << endl;map<string, int> mp2;auto it = mp1.find("王五");// void insert (InputIterator first, InputIterator last) //插入某map容器中的指定区域mp2.insert(mp1.begin(), it);print_map(mp2);cout << "---------- mp3 ----------" << endl;map<string, int> mp3{{"吴彦祖", 48}, { "金城武", 46 }};// iterator insert (const_iterator position, const value_type& val), 会按照key自动排序,不按照position的指示map<string, int>::iterator iter1 = mp3.insert(mp3.find("吴彦祖"), {"古天乐", 18});print_map(mp3);cout << "\nreturn value check" << endl;cout << "first: " << iter1->first << ", second: " << iter1->second << endl;
}
int main()
{test01();system("pause");return 0;
}result:
---------- mp1 ----------
first: Lily, second: 9
first: Lucy, second: 10
first: 李四, second: 11
first: 王五, second: 11
first: 张三, second: 12
---------- mp2 ----------
first: Lily, second: 9
first: Lucy, second: 10
first: 李四, second: 11
---------- mp3 ----------
first: 古天乐, second: 18
first: 金城武, second: 46
first: 吴彦祖, second: 48return value check
first: 古天乐, second: 18

map的删除

构造函数描述
iterator erase(const_iterator position)有的版本是返回删除的元素的迭代器,有的是返回其下一个
size_type erase (const key_type& k)返回删除了几个元素,map只能为0和1,multimap可以有多个
iterator erase(const_iterator first, const_iterator last)有的版本是返回删除的元素的迭代器,有的是返回其下一个
code:
#include <iostream>
#include <map>
using namespace std;template<typename T1, typename T2>
void print_map(const map<T1, T2>& mp)
{for (auto i_mp : mp){cout << "first: " << i_mp.first << ", second: " << i_mp.second << endl;}
}
void test01()
{cout << "---------- mp1 ----------" << endl;map<string, int> mp1{{"Lily", 9}, { "Lucy", 10 }};mp1.insert({ { "张三", 12 }, { "李四", 11 }, { "王五", 11 } });print_map(mp1);//iterator erase(const_iterator position); 有的版本是返回删除的元素的迭代器,有的是返回其下一个map<string, int>::iterator it = mp1.erase(mp1.find("张三"));cout << "it->first: " << (--it)->first << endl;// size_type erase (const key_type& k)		返回删除了几个元素,map只能为0和1,multimap可以有多个int st1 = mp1.erase("李四");cout << "int st1 = mp1.erase(key)" << endl;cout << "---------- mp1 ----------" << endl;print_map(mp1);// iterator erase(const_iterator first, const_iterator last)it = mp1.erase(mp1.begin(), --mp1.end());cout << endl;cout << "mp1.erase(mp1.begin(), --mp1.end())" << endl;		//返回指向下一个元素的迭代器print_map(mp1);cout << "it->first: " << it->first << endl;mp1.clear();cout << "mp1.clear(), mp1.size(): " << mp1.size() << endl;print_map(mp1);
}
int main()
{test01();system("pause");return 0;
}result:
---------- mp1 ----------
first: Lily, second: 9
first: Lucy, second: 10
first: 李四, second: 11
first: 王五, second: 11
first: 张三, second: 12
it->first: 王五
int st1 = mp1.erase(key)
---------- mp1 ----------
first: Lily, second: 9
first: Lucy, second: 10
first: 王五, second: 11mp1.erase(mp1.begin(), --mp1.end())
first: 王五, second: 11
it->first: 王五
mp1.clear(), mp1.size(): 0

map的大小

构造函数描述
size()返回map容器的大小
empty()返回map容器是否为空

map的交换查找,统计

|:--------😐:-------------|
|find() |如果查找到,返回查找到的迭代器,否则返回end() |
|count()|map的统计count(),map返回0或者1 |
|sort()|map的排序 |

code:
#include <iostream>
#include <map>
using namespace std;template<typename T1, typename T2>
void print_map(const map<T1, T2>& mp)
{for (auto i_mp : mp){cout << "first: " << i_mp.first << ", second: " << i_mp.second << endl;}
}
void test01()
{map<string, int> mp1{{"Lily", 9}, { "Lucy", 10 }};mp1.insert({ { "张三", 12 }, { "李四", 11 }, { "王五", 11 } });cout << "---------- mp1.size() ----------, " << mp1.size() << endl;print_map(mp1);// map的交换map<string, int> mp2;mp2["1"] = 111;mp2["2"] = 222;mp2["3"] = 333;cout << "---------- swap前----------, " << endl;print_map(mp1);print_map(mp2);cout << "---------- swap后----------, " << endl;mp1.swap(mp2);print_map(mp1);print_map(mp2);// map的查找iterator find(const key_type& _Keyval),如果查找到,返回查找到的迭代器,否则返回end()map<string, int>::iterator it = mp2.find("2");cout << "---------- mp2.find(\"2\")----------, " << endl;cout << "it->first: " << (--it)->first << endl;// size_type count(const key_type& _Keyval) map的统计count(),map返回0或者1int mp_count = mp1.count("3");cout << "---------- mp1.count(\"1\")----------, " << endl;cout << "mp_count: " << mp_count << endl;
}
int main()
{test01();system("pause");return 0;
}result:
---------- mp1.size() ----------, 5
first: Lily, second: 9
first: Lucy, second: 10
first: 李四, second: 11
first: 王五, second: 11
first: 张三, second: 12
---------- swap前----------,
first: Lily, second: 9
first: Lucy, second: 10
first: 李四, second: 11
first: 王五, second: 11
first: 张三, second: 12
first: 1, second: 111
first: 2, second: 222
first: 3, second: 333
---------- swap后----------,
first: 1, second: 111
first: 2, second: 222
first: 3, second: 333
first: Lily, second: 9
first: Lucy, second: 10
first: 李四, second: 11
first: 王五, second: 11
first: 张三, second: 12
---------- mp2.find("2")----------,
it->first: 张三
---------- mp1.count("1")----------,
mp_count: 1

map的排序

  • map的排序都是按照key来排序的,在创建map容器时就要指定好排序方式。
  • 对于普通数据类型会自动按照升序,如果要改变,可以自己写排序方式。
  • 自定义类型在创建时需要指定好排序规则,不然系统不知道怎么给排序,无法创建
code:
#include <iostream>
#include <map>
using namespace std;class Person
{friend class MyComparePerson;template<typename T1, typename T2, typename T3>friend void print_map(const map<T1, T2, T3>& mp);template<typename Person, typename T2>friend void print_map(const map<Person, T2, MyComparePerson>& mp);public:Person(string name, int age){m_name = name;m_age = age;}
private:string m_name;int m_age;
};
template<class T>
class MyCompare
{
public:bool operator()(const T &v1, const T &v2) const		// 这是需要用const限定,不然报错{return v1 > v2;}
};class MyComparePerson
{
public:bool operator()(const Person &p1, const Person &p2) const		// 这是需要用const限定,不然报错{return p1.m_age > p2.m_age;}
};template<typename T1, typename T2>
void print_map(const map<T1, T2, MyCompare<string>>& mp)
{for (auto i_mp : mp){cout << "first: " << i_mp.first << ", second: " << i_mp.second << endl;}
}template<typename Person, typename T2>
void print_map(const map<Person, T2, MyComparePerson>& mp)
{for (auto i_mp : mp){cout << "key.m_name: " << i_mp.first.m_name << ", key.m_age: " << i_mp.first.m_age << ", value: " << i_mp.second << endl;}
}void test01()
{// 普通数据类型会自动按照升序,如果要改变,可以自己写排序方式// 在创建时就要指定排序方式map<string, int, MyCompare<string>> mp2{ {"1", 20}, { "2", 30 }, { "3", 60 } };print_map(mp2);
}void test02()
{// 自定义类型在创建时需要指定好排序规则,不然系统不知道怎么给排序,无法创建// 在创建时就要指定排序方式//map<Person, int, MyComparePerson> mp1;map<Person, int, MyComparePerson> mp1;Person p1("lily", 12);Person p2("Lucy", 15);Person p3("Jim", 17);mp1.insert({{p1, 33}, {p2, 22}, {p3, 77} });print_map(mp1);
}int main()
{test01();test02();system("pause");return 0;
}result:
first: 3, second: 60
first: 2, second: 30
first: 1, second: 20
key.m_name: Jim, key.m_age: 17, value: 77
key.m_name: Lucy, key.m_age: 15, value: 22
key.m_name: lily, key.m_age: 12, value: 33

这篇关于C++系列-STL容器中的map容器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1136508

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝