3.9、map容器

3.9.1、map容器的基本概念

1、简介:

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

2、本质:

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

3、优点:

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

4、map和multimap的区别:

  • map不允许容器有重复key值元素
  • multimap允许容器有重复的key值元素

3.9.2、map构造函数和赋值

1、 功能描述:

  • 创建map容器,给map赋值

2、构造原型:

  • map mp; //采用模板实现类实现,默认构造函数
  • map(conmp map &mp); //拷贝构造

3、 赋值:

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

4、代码

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

void printMap(map<int,int>& mp)
{
	for (map<int,int>::iterator it = mp.begin(); it != mp.end(); it++)
	{
		cout << "key="<<(*it).first << " value="<<(*it).second <<endl;
	}
	cout << endl;
}

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

	//插入数据 只有insert方式
	m1.insert(pair<int, int>(1, 10));
	m1.insert(pair<int, int>(3, 30));
	m1.insert(pair<int, int>(2, 20));
	m1.insert(pair<int, int>(4, 40));
	//m1.insert(5, 50);不可以

	//遍历容器
	//map容器的特点:所有元素插入时自动被排序
	//map容器不允许插入重复的值
	printMap(m1);

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

	//赋值
	map<int, int>m3;
	m3 = m2;
	printMap(m3);
}

int main()
{
	temp01();
	system("pause");
	return 0;
}

5、总结:

  • map中所有元素都是成对出现,插入数据的时候要使用对组

6、运行结果

容器内部jmap导出 map容器原理_#include

3.9.3、map大小和交换

1、功能描述:

  • 统计map容器大小

2、函数原型:

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

3、代码

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

void printmap(const map<int,int>& st)
{
	for (map<int,int>::const_iterator it = st.begin(); it != st.end(); it++)
	{
		cout << "key=" << it->first << " value" << it->second << endl;
	}
	cout << endl;
}
void test01()
{
	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));
	m1.insert(pair<int, int>(5, 50));

	//打印容器
	cout << "m1为:" << endl;
	printmap(m1);

	//判断是否为空
	if (m1.empty())
	{
		cout << "m1为空" << endl;
	}
	else
	{
		cout << "m1不为空" << endl;
		cout << "m1的大小为:" << m1.size() << endl;
		//map容器没有容量的概念
	}
}

void test02()
{
	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));

	map<int, int>m2;
	m2.insert(pair<int, int>(6, 300));
	m2.insert(pair<int, int>(4, 100));
	m2.insert(pair<int, int>(5, 200));

	//交换前
	cout << "------交换前-------" << endl;
	printmap(m1);
	printmap(m2);

	//交换后
	cout << "------交换后-------" << endl;
	m1.swap(m2);
	printmap(m1);
	printmap(m2);
}

int main()
{
	test01();
	test02();
	system("pause");
	return 0;
}

4、总结:map没有容量的概念

  • 判断是否为空 … empty
  • 返回元素个数 … size
  • 交换容器 … swap

5、运行结果

容器内部jmap导出 map容器原理_c++_02

3.9.4、map插入和删除

1、功能描述:

  • 对map容器进行插入和删除操作

2、函数原型:

  • insert(elem); //在容器中插入元素
  • clear(); //删除容器中的所有元素
  • erase(pos); //删除pop位置的数据,返回下一个数据的位置
  • erase(beg,end); //删除[beg,end)区间的数据,返回下一个数据的位置
  • erase(key) //删除容器中与elem值匹配的元素

3、代码

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

void printMap(const map<int,int>& st)
{
	for (map<int,int>::const_iterator it = st.begin(); it != st.end(); it++)
	{
		cout << "key=" << it->first << " value=" << it->second << endl;
	}
	cout << endl;
}

void test01()
{
	map<int,int>m1;
	//插入元素
	//第一种
	m1.insert(pair<int, int>(1, 10));

	//第二种
	m1.insert(make_pair(2, 20));

	//第三种
	m1.insert(map<int,int>::value_type(3, 30));

	//第四种//不建议使用,用途可以利用key访问value
	m1[4] = 40;
	cout << m1[4] << endl;

	//cout << m1[5] << endl;//会创建出一个新元素key为5,value为0

	printMap(m1);

	//删除
	m1.erase(m1.begin());
	printMap(m1);

	//删除重载版本
	m1.erase(3);//按照key来删除
	printMap(m1);

	//清空 两钟方法
	m1.erase(m1.begin(), m1.end());//1.
	m1.clear();//2
	cout << "s1为" << endl;
	printMap(m1);
}

int main()
{
	test01();
	system("pause");
	return 0;
}

4、总结:

  • map插入方式有很多,记住一种即可
  • 插入 … insert
  • 删除 … erase
  • 清空 … clear

5、运行结果

容器内部jmap导出 map容器原理_算法_03

3.9.5、map查找和统计

1、功能描述:

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

2、函数原型:

  • find(key); //查找key是否存在,若存在返回该元素的迭代器:若不存在,返回map.end();
  • count(key); //统计key的元素个数

3、代码

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

void test01()
{
	//查找
	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>(3, 30));

	map<int,int>::iterator pos = m1.find(3);

	if (pos != m1.end())
	{
		cout << "找到元素key=" << pos->first <<" value="<<pos->second << endl;
	}
	else
	{
		cout << "未找到元素:" << endl;
	}

	//统计
	//对于map而言 统计结果 要么是0 要么是1
	//multimap的统计可能大于1
	int num=m1.count(3);
}

int main()
{
	test01();
	system("pause");
	return 0;
}

4、总结:

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

5、运行结果

容器内部jmap导出 map容器原理_c++_04

3.9.6、map排序

1、 学习目标:

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

2、主要技术点:

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

3、代码

#include<iostream>
#include<map>
#include<algorithm>//算法头文件
using namespace std;

class MyCompare
{
public:
	bool operator()(int v1, int v2)const//vm2019要加const
	{
		//降序
		return v1 > v2;
	}
};

void test01()
{
	map<int,int>m1;
	m1.insert(make_pair(1, 10));
	m1.insert(make_pair(2, 20));
	m1.insert(make_pair(3, 30));
	m1.insert(make_pair(4, 40));
	m1.insert(make_pair(5, 50));

	for (map<int,int>::iterator it = m1.begin(); it != m1.end(); it++)
	{
		cout << "key=" << it->first << " value=" << it->second << endl;
	}
	cout << endl;

	//指定排序规则为从大到小
	map<int,int, MyCompare>m2;
	m2.insert(make_pair(1, 10));
	m2.insert(make_pair(2, 20));
	m2.insert(make_pair(3, 30));
	m2.insert(make_pair(4, 40));
	m2.insert(make_pair(5, 50));
	
	for (map<int,int,MyCompare>::iterator it = m2.begin(); it != m2.end(); it++)
	{
		cout << "key=" << it->first << " value=" << it->second << endl;
	}
	cout << endl;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

4、总结:

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

5、运行结果

容器内部jmap导出 map容器原理_容器内部jmap导出_05

3.10案例-员工分组

1、案列描述

  • 公司今天招聘了十个员工(ABCDEFGHIIJ),10名员工进入公司后,需要指派在那个部门工作
  • 员工信息有:姓名,工资组成;部门分为:策划、美术、研发
  • 随机给10名员工分配部门和工资
  • 通过multimap进行信息插入,key(部门编号)value(员工)
  • 分部门显示员工信息

2、 实现步骤

  • 1、创建10名员工,放到vector中
  • 2、遍历vector容器、取出每个员工,进行随机分组
  • 3、分组后,将员工部门编号为key,具体员工作为value,放入到multimap中
  • 4、分部门显示员工信息

3、代码

#include<iostream>
#include<string>
#include<map>
#include<vector>
#include<ctime>
using namespace std;

#define CEHUA 0
#define MEISHU 1
#define YANFA 2

//抽象出员工类
class Worker
{
public:
	Worker() 
	{
		this->m_Name = "员工";
		this->m_Salary = 0;
	}

	string m_Name;
	int m_Salary;
};

void createWorker(vector<Worker>&v)
{
	string nameSeed = "ABCDEFGHIJ";
	for (int i = 0; i < 10; i++)
	{
		Worker worker;
		worker.m_Name = "员工";
		worker.m_Name += nameSeed[i];
		worker.m_Salary = 0;
		worker.m_Salary = (rand() % (20 - 6 + 1) + 6) * 1000;//6000~20000
		//将员工放入容器中
		v.push_back(worker);
	}
	
}

//员工分组
void setGroup(vector<Worker>&v, multimap<int,Worker>&m)
{
	
	for (vector<Worker>::iterator it=v.begin();it!=v.end();it++)
	{
		//随机产生部门编号
		int key=0;
		key = rand() % 3;//0 1 2
		//将员工插入到分组中
		//key为部门编号,value具体员工
		m.insert(make_pair(key, *it));
	}
}

//打印员工
void printWorker(multimap<int,Worker>&m)
{
	//0     1     2
	cout << "策划部门:" << endl;
	multimap<int, Worker>::iterator pos1 = m.find(CEHUA);
	int count = m.count(CEHUA);//统计具体人数
	int index=0;
	for (; pos1 != m.end() && index < count; pos1++, index++)
	{
		cout << "姓名:" << pos1->second.m_Name << " 薪资:" << pos1->second.m_Salary << endl;
	}

	cout << "-------------------------" << endl;
	cout << "美术部门:" << endl;
	multimap<int, Worker>::iterator pos2 = m.find(MEISHU);
	count = m.count(MEISHU);//统计具体人数
	index=0;
	for (; pos2 != m.end() && index < count; pos2++, index++)
	{
		cout << "姓名:" << pos2->second.m_Name << " 薪资:" << pos2->second.m_Salary << endl;
	}

	cout << "-------------------------" << endl;
	cout << "研发部门:" << endl;
	multimap<int, Worker>::iterator pos3 = m.find(YANFA);
	count = m.count(YANFA);//统计具体人数
	index=0;
	for (; pos3 != m.end() && index < count; pos3++, index++)
	{
		cout << "姓名:" << pos3->second.m_Name << " 薪资:" << pos3->second.m_Salary << endl;
	}
}

int main()
{   
	srand((unsigned)time(NULL));//随机数种子
	//1、创建员工
	vector<Worker>vWorker;
	createWorker(vWorker);
	测试员工是否创建成功
	//for (vector<Worker>::iterator it = vWorker.begin(); it != vWorker.end(); it++)
	//{
	//	cout << "姓名:" << it->m_Name << " 薪资:" << it->m_Salary << endl;
	//}
	//2、员工分组
	multimap<int, Worker>mWorker;
	setGroup(vWorker, mWorker);

	3、显示员工
	printWorker(mWorker);

	system("pause");
	return 0;
}

4、运行结果

创建员工后的测试结果

容器内部jmap导出 map容器原理_数据结构_06

最终结果

容器内部jmap导出 map容器原理_数据结构_07