• C++ map容器的简单用法


    1.前言

    整理map的一些用法,欢迎指正~
    有具体示例解释概念,欢迎品尝~

    2.内容

    map简介

    map是STL的关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据 处理能力 【key-value 】

    map内部是一颗红黑树(一 种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能

    map功能

    查询(log(N))、插入、删除、更改、遍历

    map具体使用

    1.构造

    头文件: < map >
    示例

    #include 
    using namespace std;
    #include 
    typedef map<string, int> MSI;  //为了使用方便,可进行类型起别名
    int main()
    {
    	map<string, int> m1;  //map构造函数
    	MSI m2;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2.增加[插入]

    #include 
    using namespace std;
    #include 
    typedef map<string, int> MSI;
    typedef map<string, int>::iterator MSIIT;
    int main()
    {
    	map<string, int> m1;  //map构造函数
    	MSI m2;
    	//四种插入方法
    	//1.insert pair
    	m2.insert(pair<string, int>("ac", 4));
    
    	//2.insert value_type
    	m2.insert(map<string, int>::value_type("as", 7));
    
    	//3.数组
    	m2["ak"] = 11;
    
    	//4.{}
    	m2.insert({ "ab",1 });
    
    	//遍历 auto x=m2.begin() 也可
    	for (MSIIT x = m2.begin(); x != m2.end(); x++)
    		cout << x->first << " " << x->second << endl;
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    在这里插入图片描述

    插入方法: insert方法 和 数组方法

    区别:insert不可覆盖已经插入的数据,而数组方法可以
    示例:

    #include 
    using namespace std;
    #include 
    typedef map<string, int> MSI;
    typedef map<string, int>::iterator MSIIT;
    int main()
    {
    	map<string, int> m1;  //map构造函数
    	MSI m2;
    	//插入方法: insert方法 和 数组方法
    	//1.insert pair
    	m2.insert(pair<string, int>("ac", 4));
    
    	//2.insert value_type
    	m2.insert(map<string, int>::value_type("as", 7));
    
    	//3.数组  
    	m2["ak"] = 11;
    
    	//4.{}
    	m2.insert({ "ab",1 });
    
    	
    	//下面一行代码检检验是否成功插入
    	//insert后返回iterator ,用 MSIIT接受 ,另一个bool则用来判断是否成功插入
    	pair<MSIIT, bool> insert_pair;
    	//1.
    	insert_pair = m2.insert({ "ak",108 });  //由于上面已经插入了 “ak”,则此次insert失败
    	if (insert_pair.second == true) puts("success!");
    	else puts("failed!");
    
    	//2.
    	insert_pair = m2.insert({ "akkkk",108 });
    	if (insert_pair.second == true) puts("success!");
    	else puts("failed!");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在这里插入图片描述

    3.遍历 [正向、反向、数组方法遍历]

    #include 
    using namespace std;
    #include 
    typedef map<string, int> MSI;
    typedef map<int, string> MIS;
    typedef map<string, int>::iterator MSIIT;  //前向迭代器
    typedef map<string, int>::reverse_iterator MSIRIT; //反向迭代器
    int main()
    {
    	map<string, int> m1;  //map构造函数
    	MSI m2;
    	//插入
    	m2["ak"] = 11;
    	m2["axcv"] = 17;
    	m2["zasfdxc"] = 21;
    	m2["mnbvnvmk"] = 91;
    	m2["bnmhk"] = 1;
    	m2["vnmhk"] = 111;
    
    	//遍历
    	//正向遍历①  auto (常用)
    	for (auto x : m2)
    		cout << x.first << " " << x.second << endl;
    	puts("");
    	//正向遍历②  正向迭代器
    	for (MSIIT x = m2.begin(); x != m2.end(); ++x)
    		cout << x->first << " " << x->second << endl;
    	puts("");
    	//反向遍历 反向迭代器
    	for (MSIRIT x = m2.rbegin(); x != m2.rend(); ++x)
    		cout << x->first << " " << x->second << endl;
    	puts("");
    
    	//Specially 当 map 时,可以用数组遍历
    	puts("");
    	MIS m3;
    	//插入
    	m3[1] = "mvbc";
    	m3[4] = "cvb";
    	//对于MIS,不存在key的value默认为"" 空
    	if (m3[2] == "") puts("none!");
    	if (m3[78] == "") puts("none!");
    	for (int i = 1; i <= 4; ++i)
    		cout << i <<" "<< m3[i] << endl;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    在这里插入图片描述
    在这里插入图片描述

    4.查找

    ①查找并返回key的迭代器 [find()]

    备注:此处迭代器为pair对象,所以用first ,second访问
    #include 
    using namespace std;
    #include 
    typedef map<string, int> MSI;
    typedef map<string, int>::iterator MSIIT;
    typedef map<int, string> MIS;
    int main()
    {
    	MSI m2;
    	//插入
    	m2["ak"] = 11;
    	m2["axcv"] = 17;
    	m2["zasfdxc"] = 21;
    	m2["mnbvnvmk"] = 91;
    	m2["bnmhk"] = 1;
    	m2["vnmhk"] = 111;
    
    	//无 "mua" 则,返回m2.end();
    	MSIIT it = m2.find("mua");
    	if (it != m2.end())  cout << "find ,its value is " << it->second << endl;
    	else cout << "not find" << endl;
    	
    	//有 "ak" ,返回该位置的迭代器
    	it = m2.find("ak");
    	if (it != m2.end())  cout << "find ,its value is " << it->second << endl;
    	else cout << "not find" << endl;
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

    ②仅判断是否存在key [count 、pair(lower_bound + upper_bound)]

    方法1: count
    map是一对一的映射关系,则count函数返回值 只可为 0 、1,即存在返回1,不存在返回0
    示例:

    #include 
    using namespace std;
    #include 
    typedef map<string, int> MSI;
    typedef map<string, int>::iterator MSIIT;
    typedef map<int, string> MIS;
    int main()
    {
    	MSI m2;
    	//插入
    	m2["ak"] = 11;
    	m2["axcv"] = 17;
    	m2["zasfdxc"] = 21;
    	m2["mnbvnvmk"] = 91;
    	m2["bnmhk"] = 1;
    	m2["vnmhk"] = 111;
    
    	//无 "mua" 则
    	int cnt = m2.count("mua");
    	if (cnt)  cout << "find" << endl;
    	else cout << "not find" << endl;
    
    	//有 "ak" 
    	cnt = m2.count("ak");
    	if (cnt)  cout << "find" << endl;
    	else cout << "not find" << endl;
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述
    方法2:pair
    前置知识:
    1.equal_range() :
    在[left , right)序列中表示一个数值的第一次出现与最后一次出现的后一位。得到相等元素的子范围,将两个迭代器以pair形式返回
    2.lower_bound()、upper_bound()
    lower_bound()返回一个 iterator 它指向在[first,last)标记的有序序列中可以插入value,而不会破坏容器顺序的第一个位置,而这个位置标记了一个不小于value 的值 即,找到>=value的位置并返回
    同理,upper_bound()找到>value的位置并返回

    示例

    #include 
    using namespace std;
    #include 
    typedef map<string, int> MSI;
    typedef map<string, int>::iterator MSIIT;
    typedef map<int, string> MIS;
    int main()
    {
    	MSI m2;
    	//插入
    	m2["ak"] = 11;
    	m2["axcv"] = 17;
    	m2["zasfdxc"] = 21;
    	m2["mnbvnvmk"] = 91;
    	m2["bnmhk"] = 1;
    	m2["vnmhk"] = 111;
    
    	//先遍历输出排序后的结果,便于后续使用
    	for (auto x : m2)
    		cout << x.first << " " << x.second << endl;
    	puts("");
    
    	//当待查找的不存在时,lower_bound == upper_bound ,均返回 大于待查找的元素 的迭代器
    	pair<MSIIT, MSIIT> p = m2.equal_range("aka");  //两个迭代器,结合为pair形式返回
    	cout << p.first->first << " " << p.first -> second << endl;
    	cout << p.second->first << " " << p.second -> second << endl;
    
    	puts("");
    
    	//当 待查找的存在时, lower_bound != upper_bound 
    	p = m2.equal_range("bnmhk");
    	cout << p.first->first << " " << p.first->second << endl;
    	cout << p.second->first << " " << p.second->second << endl;
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在这里插入图片描述

    正文:

    #include 
    using namespace std;
    #include 
    typedef map<string, int> MSI;
    typedef map<string, int>::iterator MSIIT;
    typedef map<int, string> MIS;
    int main()
    {
    	MSI m2;
    	//插入
    	m2["ak"] = 11;
    	m2["axcv"] = 17;
    	m2["zasfdxc"] = 21;
    	m2["mnbvnvmk"] = 91;
    	m2["bnmhk"] = 1;
    	m2["vnmhk"] = 111;
    
    	//先遍历输出排序后的结果,便于后续使用
    	for (auto x : m2)
    		cout << x.first << " " << x.second << endl;
    	puts("");
    
    	//当待查找的不存在时,lower_bound == upper_bound ,均返回 大于待查找的元素 的迭代器
    	pair<MSIIT, MSIIT> p = m2.equal_range("aka");  //两个迭代器,结合为pair形式返回
    	if (p.first != p.second) puts("find!");
    	else puts("not find");
    
    	puts("");
    
    	//当 待查找的存在时, lower_bound != upper_bound 
    	p = m2.equal_range("bnmhk");
    	if (p.first != p.second) puts("find!");
    	else puts("not find");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在这里插入图片描述

    5.删除 [3种]

    1.iterator erase(iterator it);//通过一个迭代器删除
    2.iterator erase(iterator first,iterator last)//删除一个范围的元素
    3.size_type erase(const Key&key); //通过关键字删除
    clear()就相当于Map.erase(Map.begin(),Map.end());

    示例:

    #include 
    using namespace std;
    #include 
    typedef map<string, int> MSI;
    typedef map<string, int>::iterator MSIIT;
    typedef map<int, string> MIS;
    int main()
    {
    	MSI m2;
    	//插入
    	m2["ak"] = 11;
    	m2["axcv"] = 17;
    	m2["zasfdxc"] = 21;
    	m2["mnbvnvmk"] = 91;
    	m2["bnmhk"] = 1;
    	m2["vnmhk"] = 111;
    
    	//先遍历输出排序后的结果,便于后续使用
    	for (auto x : m2)
    		cout << x.first << " " << x.second << endl;
    	puts("");
    
    	//1.迭代器 iterator
    	MSIIT it = m2.find("mnbvnvmk");  //找到位置
    	m2.erase(it);
    
    	//2.关键字 
    	int t1=m2.erase("mnbvnvmk");  //已经被删除过了,则此次erase无效,返回0
    	int t2 = m2.erase("vnmhk");    //成功erase ,返回1
    	cout << t1 << " " << t2 << endl;
    
    	for (auto x : m2)
    		cout << x.first << " " << x.second << endl;
    	puts("");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在这里插入图片描述

    #include 
    using namespace std;
    #include 
    typedef map<string, int> MSI;
    typedef map<string, int>::iterator MSIIT;
    typedef map<int, string> MIS;
    int main()
    {
    	MSI m2;
    	//插入
    	m2["ak"] = 11;
    	m2["axcv"] = 17;
    	m2["zasfdxc"] = 21;
    	m2["mnbvnvmk"] = 91;
    	m2["bnmhk"] = 1;
    	m2["vnmhk"] = 111;
    
    	//先遍历输出排序后的结果,便于后续使用
    	for (auto x : m2)
    		cout << x.first << " " << x.second << endl;
    	puts("");
    
    	m2.clear();
    	cout << "=====清空后=====" << endl;
    	for (auto x : m2)
    		cout << x.first << " " << x.second << endl;
    	puts("");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在这里插入图片描述

    6.swap() [两种]

    swap的作用是,交换两个容器内的所有元素

    #include 
    using namespace std;
    #include 
    typedef map<string, int> MSI;
    typedef map<string, int>::iterator MSIIT;
    typedef map<int, string> MIS;
    int main()
    {
    	MSI m1,m2;
    	//插入
    	m1["a"] = 1;
    	m1["b"] = 1;
    	m1["c"] = 1;
    	m1["d"] = 1;
    
    	m2["ak"] = 11;
    	m2["axcv"] = 17;
    	m2["zasfdxc"] = 21;
    	m2["mnbvnvmk"] = 91;
    	m2["bnmhk"] = 1;
    	m2["vnmhk"] = 111;
    
    	//先遍历输出排序后的结果,便于后续使用
    	for (auto x : m1)
    		cout << x.first << " " << x.second << endl;
    	puts("");
    	//先遍历输出排序后的结果,便于后续使用
    	for (auto x : m2)
    		cout << x.first << " " << x.second << endl;
    	puts("");
    
    	//swap
    	m1.swap(m2);
    	//也可以 : swap(m1, m2);
    
    	//swap后
    	for (auto x : m1)
    		cout << x.first << " " << x.second << endl;
    	puts("");
    	//先遍历输出排序后的结果,便于后续使用
    	for (auto x : m2)
    		cout << x.first << " " << x.second << endl;
    	puts("");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    在这里插入图片描述
    其实直接用swap()是一样的
    如果用map函数可以实现的功能,而STL Algorithm也可以完成该功能,建议用map自带函数,效率高一些。
    在这里插入图片描述

    7.排序

    默认按key升序排序,不可使用sort

    当,关键字为 结构体时,insert等会通不过, 此时要重载 < 号
    如果不重载<号,VS2019会报以下错误:
    在这里插入图片描述

    重载 <

    #include 
    using namespace std;
    #include 
    typedef map<string, int> MSI;
    typedef map<string, int>::iterator MSIIT;
    typedef map<int, string> MIS;
    //要求的排序方法:先id升序,若id相同,则name升序
    typedef struct Student {
    	int id;
    	string name;
    	bool operator <(Student const& s1) const  //重载 <
    	{
    		if (id < s1.id) return true;
    		if (id == s1.id)
    			//string 的 compare函数 前小后大为-1 相等为0 前大后小为1
    			return name.compare(s1.name) < 0;  
    		return false;
    	}
    }stu;
    
    int main()
    {
    	stu s1, s2, s3;
    	s1.id = 1;
    	s1.name = "a";
    	s2.id = 2;
    	s2.name = "b";
    	s3.id = 1;
    	s3.name = "ac";
    
    	map<stu, int> m1;   //学生信息,以及分数
    	m1.insert({ s1,20 });
    	m1.insert({ s2,98 });
    	m1.insert({ s3,9 });
    
    	//x为pair类型变量 直接 . 访问
    	for (auto x : m1)
    		cout << x.first.id << " " <<x.first.name <<" "<< x.second << endl;
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在这里插入图片描述

    3.总结

     C++ maps是一种关联式容器,包含“关键字 key/值 value”对  [键值对]
    map中由于它内部有序,是由红黑树保证,因此很多函数执行的时间复杂度都是log2N的
    
     begin()         返回指向map头部的迭代器
     end()           返回指向map末尾的迭代器
     
     size()          返回map中元素的个数
     
     clear()        删除所有元素
    
     count()         返回指定元素出现的次数
    
     empty()         判断map是否为空 [map为空则返回true]
     
     insert()        插入元素
    
     erase()         删除一个元素
    
     find()          查找一个元素
     
     rbegin()        返回一个指向map尾部的逆向迭代器
     rend()          返回一个指向map头部的逆向迭代器
     
     lower_bound()   返回键值>=给定元素的第一个位置
     upper_bound()    返回键值>给定元素的第一个位置
     	 
     max_size()      返回可以容纳的最大元素个数
     swap()           交换两个map
     
     equal_range()   返回特殊条目的迭代器对
     get_allocator() 返回map的配置器
    
     key_comp()      返回比较元素key的函数
     value_comp()     返回比较元素value的函数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    4.更新日志

    2022.8.7 整理

    欢迎评论留言、指正~~

  • 相关阅读:
    毕业设计 基于51单片机老人防跌倒GSM短信报警系统
    adb详细教程(四)-使用adb启动应用、关闭应用、清空应用数据、获取设备已安装应用列表
    js笔试题(6)
    C#目录和文件管理
    企业中WEB前端项目开发流程
    通信原理学习笔记6-4:数字解调——抽样判决的译码准则(最大后验概率准则MAP、最大似然准则ML、最小二乘/最小平方准则LS、最小距离准则)
    什么?MySQL 8.0 会同时修改两个ib_logfilesN 文件?
    中学课程辅导杂志中学课程辅导杂志社中学课程辅导编辑部2022年第24期目录
    MFC Windows 程序设计[239]之托盘通知展示(附源码)
    k8s入门之Secret(十)
  • 原文地址:https://blog.csdn.net/qq_60404548/article/details/126207983