C++中的map/multimap容器(黑马程序员)


map/multimap 容器


视频与文档链接



map/multimap容器的使用率仅次于vector和list容器


STL中的高性能高效率指的就是map容器。他可以从非常大的数据中快速的找到我想要的数据



1 map基本概念

简介:

  • map中所有元素都是pair,数据成对出现
  • pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
  • 所有元素都会根据元素的键值自动排序

本质:

  • map/multimap属于关联式容器,底层结构是用二叉树实现。

优点:

  • 可以根据key值快速找到value值

map与multimap使用方法一致,但是map和multimap也有区别

  • map不允许容器中有重复key值元素,但是value值可以重复
  • multimap允许容器中有重复key值元素,也允许value值重复

map/multimap容器的迭代器也不支持随机访问





2 map构造和赋值

功能描述:

  • 对map容器进行构造和赋值操作

函数原型:

构造:

  • map<T1, T2> mp; //map默认构造函数:
  • map(const map &mp); //拷贝构造函数

赋值:

  • map& operator=(const map &mp); //重载等号操作符



#include<iostream>
using namespace std;

#include<map>

// 打印函数
void printMap(map<int,int> &m) {
	for(map<int,int>::iterator it=m.begin();it!=m.end();it++){
		cout << "Key值:" << it->first << "    " << "数值:" << it->second << endl;
	
	
	}
}



void test01() {
	// 默认构造
	map<int, int> m1;

// 注意插入的时候一定要用对组!!
	m1.insert(pair<int, int>(1, 10));
	m1.insert(pair<int, int>(8, 205));
	m1.insert(pair<int, int>(13, 305));
	m1.insert(pair<int, int>(4, 40));
	m1.insert(pair<int, int>(4, 40));
	cout << "采用默认构造方法创建m1容器" << endl;
	printMap(m1);
	cout << "map容器不允许有重复的Key值元素!和set容器一样编译器并不会报错,但最后还是相当于没插这个数。" << endl<<endl;


	// 拷贝构造
	map<int, int> m2(m1);
	cout << "m2拷贝自m1" << endl;
	printMap(m2); 
	cout << endl;


	// 等号赋值
	map<int, int>m3;
	m3.insert(pair<int, int>(1, 10));
	m3.insert(pair<int, int>(2, 20));
	m3.insert(pair<int, int>(3, 30));
	m3.insert(pair<int, int>(4, 40));
		cout << "容器m3如下:" << endl;
	printMap(m3); cout << endl;

	cout << "m4=m3" << endl;
	map<int, int>m4 = m3;
	printMap(m4); cout << endl;

}

int main() {
	test01();
	cin.get();
	return 0;

}

在这里插入图片描述

总结:map中所有元素都是成对出现,插入数据时要使用对组





3 map大小和交换

功能描述:

  • 统计map容器大小以及交换map容器

函数原型:

  • size(); //返回容器中元素的数目
  • empty(); //判断容器是否为空
  • swap(st); //交换两个集合容器



#include<iostream>
using namespace std;

#include<map>

// 打印函数
void printMap(map<int, int>& m) {
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) {
		cout << "Key值:" << it->first << "    " << "数值:" << it->second << endl;


	}
	cout << endl;
}



void test01() {
	// 创建map容器
	map<int, int> m1;

	m1.insert(pair<int, int>(1, 10));
	m1.insert(pair<int, int>(2, 20));
	m1.insert(pair<int, int>(3, 30));
	m1.insert(pair<int, int>(4, 40));
	cout << "m1交换前:" << endl;
	cout << "大小:" << m1.size() << endl;
	printMap(m1); cout << endl;
	

	// 另一个map容器
	map<int, int> m2;

	m2.insert(pair<int, int>(9, 90));
	m2.insert(pair<int, int>(10 ,100));
	m2.insert(pair<int, int>(11, 110));
	m2.insert(pair<int, int>(12, 120));
	m2.insert(pair<int, int>(15, 150));
	cout << "m2交换前:" << endl;
	cout << "大小:" << m2.size() << endl;
	printMap(m2); cout << endl;


	cout << "m1交换后:" << endl;
	m1.swap(m2);
	cout << "大小:" << m1.size() << endl;
	printMap(m1);
	cout << "m2交换后:" << endl;
	cout << "大小:" << m2.size() << endl;
	printMap(m2);

   
}

int main() {
	test01();
	cin.get();
	return 0;

}

在这里插入图片描述

总结:

  • 统计大小 — size
  • 判断是否为空 — empty
  • 交换容器 — swap





4 map插入和删除

功能描述:

  • map容器进行插入数据和删除数据

函数原型:

  • insert(elem); //在容器中插入元素。
  • clear(); //清除所有元素
  • erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
  • erase(beg, end); //删除迭代器区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
  • erase(key); //删除容器中键值为key的元素


map/multimap有以下四种插入方式

map<int, int> m1;
map<int, int> m2;
map<int, int> m3;

// 第一种是常规插入方式。利用对组
m1.insert(pair<int, int>(1, 10));

// 第二种插入方式。也是利用对组,不过不需要写模板参数列表了。
m2.insert(make_pair(5, 50));

// 第三种,比较长,不建议使用
m3.insert(map<int, int>::value_type(9, 90));

// 第四种,像数组一样。重载了[]
// 不过有缺陷。如果m[n]中的键值n不存在,那么直接cout<<m[n]时,m[n]=0;
// 也就是说如果键值不存在,且没有为m[n]赋值。那么打印m[n]时会为map容器创建出一个key为n,value为0的元素
// 用这种方式可能会插错数
//[]不建议去插数,但推荐用这种方法去访问元素,很方便
m1[4] = 50;
m1[5] = 70;

第三种插入方式少用。
第四种方式不建议去插数,但推荐用这种方法代替迭代器,通过key去访问value
map容器的迭代器不支持随机访问,访问元素时比较麻烦




综合:

#include<iostream>
using namespace std;
#include<map>

// 打印函数
void printMap(map<int, int>& m) {
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) {
		cout << "Key值:" << it->first << "    " << "数值:" << it->second << endl;


	}

	
	cout << endl;
}


void test01() {
	map<int, int> m1;
	map<int, int> m2;
	map<int, int> m3;

	// 插入方法,第一种,利用对组
	cout << "第一种插入方法:" << endl;
	m1.insert(pair<int, int>(1, 10));
	m1.insert(pair<int, int>(2, 20));
	m1.insert(pair<int, int>(3, 30));
	m1.insert(pair<int, int>(4, 40));
	cout << "m1里的元素为:" << endl;
	printMap(m1);
	cout << endl;

	// 第二种插入方法,make_pair
	cout << "第二种插入方法:" << endl;
	m2.insert(make_pair(5, 50));
	m2.insert(make_pair(6, 60));
	m2.insert(make_pair(7, 70));
	m2.insert(make_pair(8, 80));
	cout << "m2里的元素为:" << endl;
	printMap(m2);
	cout << endl;


	// 第三种插入方法,::value_type,不推荐
	cout << "第三种插入方法:" << endl;
	m3.insert(map<int, int>::value_type(9, 90));
	m3.insert(map<int, int>::value_type(10, 100));
	m3.insert(map<int, int>::value_type(11, 110));
	m3.insert(map<int, int>::value_type(12, 120));
	cout << "m3里的元素为:" << endl;
	printMap(m3);
	cout << endl;

	// 第四种
	m1[5] = 50;
	m1[6] = 70;
	cout << "第四种方式:" << endl;
	cout << "m1里的元素为:" << endl;
	// 直接打印cout<<m1[7],会为容器创建一个键值为7 value为0的元素
	// cout<<m1[7]<<endl;
	printMap(m1); 
	cout << endl;




	// 删除,只用M1做实验
	cout << "依次删除m1中键值为6的元素、m1.begin()、[m1.begin()++,--m1.end())后" << endl;
	m1.erase(6);
	m1.erase(m1.begin());
	m1.erase(m1.begin()++,--m1.end());
	printMap(m1); cout << endl;


	// 清空
	m2.clear();
	cout << "清空容器m2" << endl;
	cout << "m2.size()=" << m2.size() << endl;
}

int main() {
	test01();
	cin.get();
	return 0;


}

在这里插入图片描述

总结:

  • map插入和删除方式很多,要熟练掌握
  • 插入 — insert
  • 删除 — erase
  • 清空 — clear





5 map查找和统计

功能描述:

  • 对map容器进行查找数据以及统计数据

函数原型:

  • find(key); //查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();
  • count(key); //统计key的元素个数,对于map容器。元素个数要么为0,要么为1


#include<iostream>
using namespace std;

#include<map>

// 打印函数
void printMap(map<int, int>& m) {
	for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) {
		cout << "Key值:" << it->first << "    " << "数值:" << it->second << endl;


	}
	cout << endl;
}



void test01() {
	// 创建map容器
	map<int, int> m1;

	m1.insert(make_pair(1, 10));
	m1.insert(make_pair<int, int>(2, 20));
	m1.insert(make_pair<int, int>(3, 30));
	m1.insert(make_pair<int, int>(4, 40));
	m1.insert(make_pair<int, int>(4, 50));
	m1.insert(make_pair<int, int>(3, 60));
	cout << "m1里的元素为:" << endl;
	printMap(m1); 
	cout << "m1.size()=" << m1.size() << endl;
	cout << endl;
	map<int, int>::iterator it1 = m1.find(5);
	map<int, int>::iterator it2 = m1.find(4);
	cout << "查找m1容器中键值为5的元素" << endl;
	if (it1 == m1.end()) {
		cout << "m1容器里没有键值为5的元素!!" << endl << endl;;

	}
	else {
		cout << "键值为5的元素已找到!" << endl;
		cout << "它的value值为" << it1->second << endl << endl;;
	}

	cout << "查找m1容器中键值为4的元素" << endl;
	if (it2 == m1.end()) {

		cout << "m1容器里没有键值为4的元素!!" << endl << endl;;
	}
	else {
		cout << "键值为4的元素已找到!" << endl;
		cout << "它的value值为" << it2->second << endl<<endl;
	}


	cout << "m1里key为3的元素的个数"<<m1.count(3);
	cout << endl << "m1里key为6的元素的个数"<<m1.count(6) << endl;

     
}

int main() {
	test01();
	cin.get();
	return 0;

}

在这里插入图片描述

总结:

  • 查找 — find (返回的是迭代器)
  • 统计 — count (对于map,结果为0或者1

map容器插重复键值元素,等于白插






6 map容器排序

学习目标:

  • map容器默认排序规则为 按照key值进行 从小到大排序,掌握如何改变排序规则

因为map是根据key值进行排序的,所以更改的排序规则针对的是key值。必须在容器插入数据前就给出排序规则。


主要技术点:

  • 利用仿函数,可以改变排序规则


#include<iostream>
using namespace std;

#include<map>
#include<string>

class Person {
public:
	string m_Name;
	int m_Age;
	Person(string name, int age) :m_Name(name), m_Age(age) {}


};
// 针对内置数据类型的排序
class MyCompare1 {
public:
	// 修改内置数据类型排序为降序
	bool operator()(int v1, int v2) const{
		return v1 > v2;

	}
	// 关于自定义数据类型的排序规则
	// 升序排序
	bool operator()(Person p1, Person p2)const
	{
		return p1.m_Age < p2.m_Age;

	}

};
class MyCompare2
{
public:
	bool operator()(int v1, int v2) const
	{
		return v1<v2;
	}
};

void test01() {
	// 创建map容器
	map<int, int,MyCompare1> m1;

	m1.insert(pair<int, int>(1, 10));
	m1.insert(pair<int, int>(2, 20));
	m1.insert(pair<int, int>(3, 30));
	m1.insert(pair<int, int>(4, 40));
	cout << "针对内置数据类型的排序修改,根据key值从大到小排序" << endl;
	for (map<int, int, MyCompare1>::iterator it = m1.begin(); it != m1.end(); it++) {
		cout << "Key值:" << it->first << "   " << "数值:" << it->second << endl;


	}
	cout << endl;


	// 针对自定义类型的map容器
	map<Person,string, MyCompare1> m2;
	Person p1("aweawe", 25);
	Person p2("wkkkk", 36);
	Person p3("EDG", 66);
	Person p4("RNG", 66);
	Person p5("TES", 86);
	Person p6("JDG", 99);
	m2.insert(pair<Person,string>(p1, p1.m_Name));
	m2.insert(pair<Person,string>(p2, p2.m_Name));
	m2.insert(pair<Person, string>(p3, p3.m_Name));
	m2.insert(pair<Person, string>(p4, p4.m_Name));
	m2.insert(pair<Person, string>(p5, p5.m_Name));
	cout << "m2.size()=" << m2.size() << endl<<endl;
	


	cout << "针对自定义数据类型的排序修改,根据年龄从小到大排序" << endl;
	for (map<Person,string, MyCompare1>::iterator it = m2.begin(); it != m2.end(); it++) {
		cout << "Key值(年龄):" << it->first.m_Age<< "   " << "姓名:" << it->second << "    "<<endl;


	}
	cout << endl;
	map<Person, string, MyCompare1>::iterator it1 = m2.find(p4);
	cout << "查找m2容器有没有年龄为66的元素" << endl;
	if (it1 == m2.end()) {
		cout << "容器里没有年龄为66的元素!!!" << endl << endl;;

	}
	else {
		cout << "已找到!" << endl;
		cout << "它的姓名为" << it1->second << endl << endl;;
	}
	map<Person, string, MyCompare1>::iterator it2 = m2.find(p6);
	cout << "查找m2容器有没有年龄为99的元素" << endl;
	if (it2 == m2.end()) {
		cout << "容器里没有年龄为99的元素!!!" << endl << endl;;

	}
	else {
		cout << "已找到!" << endl;
		cout << "它的姓名为" << it1->second << endl << endl;;
	}




}

int main() {
	test01();
	cin.get();
	return 0;

}

在这里插入图片描述

总结:

  • 利用仿函数可以指定map容器的排序规则
  • 对于自定义数据类型,map必须要指定排序规则,同set容器






  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
C++ STLmapmultimap是关联容器,用于存储键值对(key-value pairs),其每个键(key)唯一对应一个值(value)。 map是一个有序容器,根据键的大小进行自动排序,默认按照键的升序进行排序。每个键只能在map出现一次,如果尝试插入具有相同键的元素,新元素将替代旧元素。 multimap也是一个有序容器,与map不同的是,它允许多个具有相同键的元素存在。多个具有相同键的元素将按照插入的顺序进行存储,而不会自动排序。 这两个容器都提供了一系列的操作函数,如insert、erase、find等,用于插入、删除和查找元素。 以下是一个使用map的简单示例: ```cpp #include <iostream> #include <map> int main() { std::map<std::string, int> scores; scores.insert(std::make_pair("Alice", 90)); scores.insert(std::make_pair("Bob", 80)); scores.insert(std::make_pair("Charlie", 70)); // 查找并输出Bob的分数 std::cout << "Bob's score: " << scores["Bob"] << std::endl; // 遍历并输出所有键值对 for (const auto& pair : scores) { std::cout << pair.first << ": " << pair.second << std::endl; } return 0; } ``` 上述示例,我们创建了一个存储string类型键和int类型值的map容器scores。通过insert函数依次插入了三个键值对。然后我们通过scores["Bob"]来获取Bob的分数,并输出结果为80。 接着我们使用范围-based for循环遍历map的所有键值对,并输出每个键值对的键和值。 multimap的用法与map类似,只是它允许多个具有相同键的元素存在。 这些关联容器在查找和插入操作上具有较高的效率,特别适用于需要根据键进行快速查找的场景。在实际应用,你可以根据自己的需求选择适合的容器类型。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值