一、map容器的特点
1、所有元素都会根据元素的键值自动排序
2、所有的元素都是pair,同时拥有键值和实值。 第一个参数:键值 第二个参数:实值
3、map容器的键值唯一 不可变 实值 可变。
二、map容器的插入、遍历
-
void test()
-
{
-
/*
-
map/multimap常用API
-
map构造函数
-
map<T1, T2> mapTT;//map默认构造函数:
-
map(const map &mp);//拷贝构造函数
-
map赋值操作
-
map& operator=(const map &mp);//重载等号操作符
-
swap(mp);//交换两个集合容器
-
map大小操作
-
size();//返回容器中元素的数目
-
empty();//判断容器是否为空
-
map插入数据元素操作
-
map.insert(...); //往容器插入元素,返回pair<iterator,bool>
-
map<int, string> mapStu;
-
//第一种 通过pair的方式插入对象
-
mapStu.insert(pair<int, string>(3, "小张"));
-
// 第二种 通过pair的方式插入对象
-
mapStu.inset(make_pair(‐1, "校长"));
-
// 第三种 通过value_type的方式插入对象
-
mapStu.insert(map<int, string>::value_type(1, "小李"));
-
// 第四种 通过数组的方式插入值
-
mapStu[3] = "小刘";
-
mapStu[5] = "小王";
-
map删除操作
-
clear();//删除所有元素
-
erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
-
erase(beg,end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
-
erase(keyElem);//删除容器中key为keyElem的对组。
-
map查找操作
-
find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;/若不存在,返回m
-
ap.end();
-
count(keyElem);//返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是
-
对multimap来说,值可能大于1。
-
lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
-
upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
-
equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器。
-
*/
-
//存放9527‐‐"星爷" 10086‐"移动" 10010‐‐"联通" 10000‐‐"电信"
-
//int为键值的类型 string为实值的类型
-
map<int, string> m;
-
//第1种:
-
m.insert(pair<int, string>(9527, "星爷"));
-
//第2种:(推荐)
-
m.insert(make_pair(10086, "移动"));
-
//第3种:
-
m.insert(map<int, string>::value_type(10010, "联通"));
-
//第4种:读map容器数据的时候 推荐
-
m[10000] = "电信";//m.insert(make_pair(10000,"电信"));
-
//m[10] 寻找key为10的实值
-
//但是:如果容器中没有key为10 使用m[10] 会创建一个key为10实值为空的 对组
-
//如果容器中有key为10 那么m[10]代表key=10的实值
-
//建议:10是存在的
-
cout << m[10] << endl;
-
myPrintMap01(m);
-
#if 0
-
for_each(m.begin(), m.end(), [](pair<int, string> val) {
-
cout << "key=" << val.first << ", value=" << val.second << endl;
-
});
-
#endif
-
//只想查看key==9527 的实值 (保证key是存在的)
-
cout << m[9527] << endl;//"星爷"
-
cout << m[10010] << endl;//"联通"
-
//如果不能确定key值是否存在
-
map<int, string>::const_iterator ret;
-
ret = m.find(10086);
-
if (ret == m.end())
-
{
-
cout << "未找到相关节点" << endl;
-
}
-
else
-
{
-
//ret代表的是key=10086的对组的迭代器
-
cout << "找到相关节点:key=" << (*ret).first << ", value=" << (*ret).second << endl;
-
}
-
}
三、multimap案例
公司今天招聘了 5 个员工,5 名员工进入公司之后,需要指派员工在那个部门工作 人员信息有: 姓名 年龄 电话 工资等组成 通过 Multimap 进行信息的插入 保存 显示 分部门显示员工信息 显示全部员工信息
-
#include<iostream>
-
#include<map>
-
#include<algorithm>
-
#include<time.h>
-
#include<string>
-
#include<vector>
-
using namespace std;
-
#define SALE_DEPATMENT 1 //销售部门
-
#define DEVELOP_DEPATMENT 2 //研发部门
-
#define FINACIAL_DEPATMENT 3 //财务部门
-
#define ALL_DEPATMENT 4 //所有部门
-
class Person {
-
public:
-
string name;
-
int age;
-
double salary;
-
string tele;
-
};
-
//创建五个员工
-
void createperson(vector<Person> worker)
-
{
-
string tmp = "ABCDE";
-
for (int i = 0; i < tmp.size(); ++i)
-
{
-
Person p;
-
p.name = "员工";
-
p.name += tmp[i];
-
p.age = rand() % 30 + 20;
-
p.salary = rand() % 20000 + 10000;
-
p.tele = "010-8888888";
-
worker.push_back(p);
-
}
-
}
-
//5 名员工分配到不同的部门
-
void Personbygroup(vector<Person> &list, multimap<int, Person> &plist)
-
{
-
int operate = -1;//用户的操作
-
for (vector<Person>::iterator it; it != list.end(); it++)
-
{
-
cout << "当前员工信息" << endl;
-
cout << "姓名:" << it->name << "年龄:" << it->age << "工资"
-
<< it->salary << "电话" << it->tele << endl;
-
cout << "请对该员工进行部门分配(1 销售部门, 2 研发部门, 3 财务部门):" << endl;
-
cin >> operate;
-
while (true)
-
{
-
if (operate == SALE_DEPATMENT) {
-
plist.insert(make_pair(SALE_DEPATMENT, *it));
-
break;
-
}
-
else if (operate == DEVELOP_DEPATMENT) {
-
plist.insert(make_pair(DEVELOP_DEPATMENT, *it));
-
break;
-
}
-
else if (operate == FINACIAL_DEPATMENT) {
-
plist.insert(make_pair(FINACIAL_DEPATMENT, *it));
-
break;
-
}
-
else {
-
cout << "您的输入有误,请重新输入(1 销售部门, 2 研发部门, 3 财务部门):" << endl;
-
cin >> operate;
-
}
-
}
-
}
-
cout << "员工部门分配完毕!" << endl;
-
cout << "***********************************************************" << endl;
-
}
-
//打印员工信息
-
void Printlist(multimap<int, Person> &mlist , int myoperate)
-
{
-
if (myoperate == ALL_DEPATMENT) {
-
for (multimap<int, Person>::iterator it = mlist.begin(); it != mlist.end(); it++)
-
{
-
cout << "姓名:" << it->second.name << " 年龄:" << it->second.age
-
<< " 工资:" << it->second.salary << " 电话:" << it->second.tele << endl;
-
}
-
return;
-
}
-
multimap<int, Person>::iterator it = mlist.find(myoperate);
-
int depatCount = mlist.count(myoperate);
-
int num = 0;
-
if (it != mlist.end()) {
-
while (it != mlist.end() && num < depatCount) {
-
cout << "姓名:" << it->second.name << " 年龄:" << it->second.age \
-
<< " 工资:" << it->second.salary << " 电话:" << it->second.tele << endl;
-
it++;
-
num++;
-
}
-
}
-
}
-
//根据用户操作显示不同部门的人员列表
-
void ShowPersonList(multimap<int, Person>& plist, int myoperate) {
-
switch (myoperate)
-
{
-
case SALE_DEPATMENT:
-
Printlist(plist, SALE_DEPATMENT);
-
break;
-
case DEVELOP_DEPATMENT:
-
Printlist(plist, DEVELOP_DEPATMENT);
-
break;
-
case FINACIAL_DEPATMENT:
-
Printlist(plist, FINACIAL_DEPATMENT);
-
break;
-
case ALL_DEPATMENT:
-
Printlist(plist, ALL_DEPATMENT);
-
break;
-
}
-
}
-
//用户操作菜单
-
void PersonMenue(multimap<int, Person>& plist) {
-
int flag = -1;
-
int isexit = 0;
-
while (true) {
-
cout << "请输入您的操作((1 销售部门, 2 研发部门, 3 财务部门, 4所有部门, 0 退出):" << endl;
-
cin >> flag;
-
switch (flag)
-
{
-
case SALE_DEPATMENT:
-
ShowPersonList(plist, SALE_DEPATMENT);
-
break;
-
case DEVELOP_DEPATMENT:
-
ShowPersonList(plist, DEVELOP_DEPATMENT);
-
break;
-
case FINACIAL_DEPATMENT:
-
ShowPersonList(plist, FINACIAL_DEPATMENT);
-
break;
-
case ALL_DEPATMENT:
-
ShowPersonList(plist, ALL_DEPATMENT);
-
break;
-
case 0:
-
isexit = 1;
-
break;
-
default:
-
cout << "您的输入有误,请重新输入!" << endl;
-
break;
-
}
-
if (isexit == 1) {
-
break;
-
}
-
}
-
}
-
int main()
-
{
-
vector<Person> vlist; //创建的 5 个员工 未分组
-
multimap<int, Person> plist; //保存分组后员工信息
-
//创建 5 个员工
-
createperson(vlist);
-
//5 名员工分配到不同的部门
-
Personbygroup(vlist, plist);
-
//根据用户输入显示不同部门员工信息列表 或者 显示全部员工的信息列表
-
PersonMenue(plist);
-
system("pause");
-
return 0;
-
}
四、STL 容器使用时机
vector 的使用场景:比如软件历史操作记录的存储,我们经常要查看历史记录, 比如上一次的记录,上上次的记录,但却不会去删除记录,因为记录是事实的描 述。
deque 的使用场景:比如排队购票系统,对排队者的存储可以采用 deque, 支持头端的快速移除,尾端的快速添加。如果采用 vector,则头端移除时,会移动 大量的数据,速度慢。
vector 与 deque 的比较: 一:vector.at()比 deque.at() 效率高,比如 vector.at(0)是固定的,deque 的开始位置 却是不固定的。
二:如 果有大量释放操作的话,vector 花的时间更少,这跟二者的内部实现有关。
三: deque 支持头部的快速插入与快速移除,这是 deque 的优点。 list 的使用场景: 比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不确实位置元素的移除 插入。
set 的使用场景:比如对手机游戏的个人得分记录的存储,存储要求从高 分到低分的顺序排列。 map 的使用场景:比如按 ID 号存储十万个用户,想要 快速要通过 ID 查找对应的用户。二叉树的查找效率,这时就体现出来了。如果是 vector 容器,最坏的情况下可能要遍历完整个容器才能找到该用户。