STL常见容器目录:
- 8.map/ multimap容器
- 8.1 map基本概念
- 8.2 map构造和赋值
- 8.3 map大小和交换
- 8.4 map插入和删除
- 8.5 map查找和统计
- 8.6 map容器排序
- 8.6.1 内置类型排序
- 8.6.2 自定义类型排序
- 8.6.3 自定义和内置类型混合排序
- 8.7 实例
- 8.7.1 案例描述
- 8.7.2 实现步骤
8.map/ multimap容器
两者基本一致,除了以下区别:
map和multimap区别:
- map
不允许
容器中有重复key值
元素;- multimap
允许
容器中有重复key值
元素。
注意:对于value值都可以重复
8.1 map基本概念
简介:
- map中所有元素都是
pair
; - pair中第一个元素为
key(键值)
,起到索引作用,第二个元素为value(实值)
(可以根据key值快速找到value值); - 所有元素都会根据元素的
键值自动排序
;
本质:
- map/multimap属于关联式容器,底层结构是用二叉树实现(同set容器)。
8.2 map构造和赋值
构造:
map<T1, T2> mp;
//map默认构造函数:map(const map &mp);
//拷贝构造函数
赋值:
map& operator=(const map &mp);
//重载等号操作符
总结:map中所有元素都是成对出现,插入数据时候要使用对组。
8.3 map大小和交换
函数原型:
size();
//返回容器中元素的数目empty();
//判断容器是否为空swap(st);
//交换两个集合容器
8.4 map插入和删除
函数原型:
insert(elem);
//在容器中插入元素(四种方式)。clear();
//清除所有元素erase(pos);
//删除pos迭代器所指的元素,返回下一个元素的迭代器。erase(beg, end);
//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。erase(key);
//删除容器中值为key的元素。
示例:
#include <map>//包含头文件(multimap头文件一样)
void Printmap(map<int, int>m)//按照key值排序(默认升序)
{
for (map<int,int>::iterator it = m.begin(); it != m.end(); it++) {
cout << "key=" << (*it).first << " value= " << it->second << endl;;
}
cout << endl;
}
void test01()
{
map<int, int>m;
//四种插入方式(多用前两种)
m.insert(pair<int, int>(9, 90));//pair匿名对象
m.insert(make_pair(8, 80));
m.insert(map<int, int>::value_type(7, 70));
m[6] = 60;//key=6,value=60
Printmap(m);
cout << "方括号访问元素:" << m[9] << endl;//可利用[key]访问对于value值
m.erase(7);//删除key=7的元素(若无相应key值,则不删除)
Printmap(m);
}
8.5 map查找和统计
函数原型:
find(key);
//查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end();count(key);
//统计key的元素个数(map返回0或1;mutimap可能大于1)
8.6 map容器排序
主要技术点:
- 利用
仿函数
,可以改变排序规则。(默认升序)
8.6.1 内置类型排序
示例:
#include <map>
class MyCompare {
public:
bool operator()(int v1, int v2) const
{
return v1 > v2;//降序
}
};
void test02()
{
//默认从小到大排序
//利用仿函数实现从大到小排序
map<int, int, MyCompare> m;
m.insert(make_pair(1, 10));
m.insert(make_pair(2, 20));
m.insert(make_pair(3, 30));
m.insert(make_pair(4, 40));
m.insert(make_pair(5, 50));
for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++) {
cout << "key:" << it->first << " value:" << it->second << endl;
}
}
输出;
key:5 value:50
key:4 value:40
key:3 value:30
key:2 value:20
key:1 value:10
8.6.2 自定义类型排序
示例:
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
//仿函数
class MyCompare
{
public:
bool operator()(const Person& v1, const Person& v2) const
{
//按照年龄进行排序 降序
return v1.m_Age > v2.m_Age;
}
};
void test03()
{
//指定排序规则
map<Person,Person, MyCompare> m;//改变排序顺序需要在插入数据之前改变
//插入自定义数据
Person p1("刘备", 23);
Person p2("关羽", 27);
Person p3("张飞", 25);
Person p4("赵云", 21);
m.insert(make_pair(p1,p1));
m.insert(make_pair(p2,p2));
m.insert(make_pair(p3,p3));
m.insert(make_pair(p4,p4));
for (map<Person, Person, MyCompare>::iterator it = m.begin(); it != m.end(); it++) {
cout << "姓名:" << it->second.m_Name << " 年龄:" << it->second.m_Age << endl;
}
}
输出:
姓名:关羽 年龄:27
姓名:张飞 年龄:25
姓名:刘备 年龄:23
姓名:赵云 年龄:21
8.6.3 自定义和内置类型混合排序
示例:
#include <map>
class Person
{
public:
Person(string name, int age)
{
this->m_Name = name;
this->m_Age = age;
}
string m_Name;
int m_Age;
};
void test04()
{
map<int,Person> m;//若要改变排序顺序需要在插入数据之前改变
//因为map排序是按照key值排序,此处key为整型,编译器可自行排序(升序)
//降序参照8.6.1
//插入自定义数据
Person p1("刘备", 23);
Person p2("关羽", 27);
Person p3("张飞", 25);
Person p4("赵云", 21);
m.insert(make_pair(p1.m_Age,p1));
m.insert(make_pair(p2.m_Age, p2));
m.insert(make_pair(p3.m_Age, p3));
m.insert(make_pair(p4.m_Age, p4));
for (map<int, Person>::iterator it = m.begin(); it != m.end(); it++) {
cout << "姓名:" << it->second.m_Name << " 年龄:" << it->second.m_Age << endl;
}
}
输出:
姓名:赵云 年龄:21
姓名:刘备 年龄:23
姓名:张飞 年龄:25
姓名:关羽 年龄:27
总结:
- 利用仿函数可以指定map容器的排序规则;
- 对于自定义数据类型,map必须要指定排序规则,同set容器;
8.7 实例
8.7.1 案例描述
- 公司今天招聘了10个员工(ABCDEFGHIJ),10名员工进入公司之后,需要指派员工在那个部门工作;
- 员工信息有: 姓名 工资组成;部门分为:策划、美术、研发;
- 随机给10名员工分配部门和工资;
- 通过multimap进行信息的插入 key(部门编号) value(员工);
- 分部门显示员工信息。
8.7.2 实现步骤
- 创建10名员工,放到vector中
- 遍历vector容器,取出每个员工,进行随机分组
- 分组后,将员工部门编号作为key,具体员工作为value,放入到multimap容器中
- 分部门显示员工信息
案例代码:
#include<iostream>
using namespace std;
#include <vector>
#include <string>
#include <map>
#include <ctime>
#define CEHUA 0//策划0
#define MEISHU 1//美术1
#define YANFA 2//研发2
class Person
{
public:
Person(string name, int wages)
{
this->m_name = name;
this->m_wages = wages;
}
string m_name;
int m_wages;//工资范围:10000-20000
};
//创建10名员工,放到vector中
void creat_person(vector<Person>&v)
{
string nameSeed = "ABCDEFGHIJ";
for (int i = 0; i < 10; i++)
{
string str ="员工";
str += nameSeed[i];//形成“员工i”的字符串
Person p(str, rand() % 10001 + 10000);//rand() % 10001 + 10000产生10000-20000
v.push_back(p);
}
}
//随机分组,员工部门编号作为key,具体员工作为value,放入到multimap容器中
void set_group(vector<Person>& v,multimap<int,Person>&m)
{
for (int i = 0; i < v.size(); i++)
{
m.insert(make_pair(rand() % 3, v[i]));
}
}
//分部门显示员工信息
void show_person(multimap<int, Person>& m)
{
cout << "策划部门:" << endl;
multimap<int, Person>::iterator pos = m.find(CEHUA);//找到第一个key=0的位置
int count = m.count(CEHUA);//统计该部门人员数量
for (int i = 0; pos != m.end() && i < count; i++, pos++)
{
//因为multimap容器按照key值自动排序
// 所以从pos位置开始count个人员都是该部门的
cout << "姓名:" << pos->second.m_name << " 工资:" << pos->second.m_wages << endl;
}
cout << "************************" << endl;
cout << "美术部门:" << endl;
pos = m.find(MEISHU);
count = m.count(MEISHU);
for (int i = 0; pos != m.end() && i < count; i++, pos++)
{
cout << "姓名:" << pos->second.m_name << " 工资:" << pos->second.m_wages << endl;
}
cout << "************************" << endl;
cout << "研发部门:" << endl;
pos = m.find(YANFA);
count = m.count(YANFA);
for (int i = 0; pos != m.end() && i < count; i++, pos++)
{
cout << "姓名:" << pos->second.m_name << " 工资:" << pos->second.m_wages << endl;
}
}
int main()
{
srand((unsigned int)time(NULL));
vector<Person>v;
multimap<int, Person> m;
creat_person(v);
set_group(v, m);
show_person(m);
system("pause");
return 0;
}
某一次随机输出: