STL常用容器--map/multimap容器
1 map/multimap基本概念
map的特性是,所有元素都会根据元素的键值自动排序。map所有的元素都是pair,同时拥有实值和键值,pair的第一元素被视为键值,第二元素被视为实值,map不允许两个元素有相同的键值。
我们可以通过map的迭代器改变map的键值吗?答案是不行,因为map的键值关系到map元素的排列规则,任意改变map键值将会严重破坏map组织。如果想要修改元素的实值,那么是可以的。
map和list拥有相同的某些性质,当对它的容器元素进行新增操作或者删除操作时,操作之前的所有迭代器,在操作完成之后依然有效,当然被删除的那个元素的迭代器必然是个例外。
multimap和map的操作类似,唯一区别multimap键值可重复。
map和multimap都是以红黑树为底层实现机制。
2 map/multimap常用API
2.1 map构造函数
map<T1, T2> mapTT; //map默认构造函数:
map(const map &mp); //拷贝构造函数
2.2 map赋值操作
map& operator=(const map &mp); //重载等号操作符
swap(mp); //交换两个集合容器
2.3 map大小操作
size(); //返回容器中元素的数目
empty(); //判断容器是否为空
2.4 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, "小李"));
// 第四种 通过数组的方式插入值
// 通过第四种方式插入,如果指定的key原本不存在,会生成一个指定值为key,其value为0的pair插入到容器中
mapStu[3] = "小刘";
mapStu[5] = "小王";
2.5 map删除操作
clear(); //删除所有元素
erase(pos); //删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg,end); //删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(keyElem); //删除容器中key为keyElem的对组。
2.6 map查找操作
find(key); //查找键key是否存在,若存在,返回该键的元素的迭代器;/若不存在,返回map.end();
count(keyElem); //返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。
lower_bound(keyElem); //返回第一个key>=keyElem元素的迭代器。
upper_bound(keyElem); //返回第一个key>keyElem元素的迭代器。
equal_range(keyElem); //返回容器中key与keyElem相等的上下限的两个迭代器。
3 案例
3.1 Key为内置数据类型
#include <iostream>
#include <map>
using namespace std;
void printMap(map<string, int> &M)
{
for (map<string, int>::iterator it = M.begin(); it != M.end(); ++it)
{
cout << it->first << " " << it->second << endl;
}
}
int main()
{
map<string,int> M;
// 插入
M.insert(make_pair("李四", 20));
M.insert(make_pair("张三", 18));
M.insert(make_pair("王五", 21));
printMap(M);
cout << "============" << endl;
M.erase("李四");
printMap(M);
cout << "============" << endl;
map<string, int>::iterator ret = M.find("张三");
if (ret != M.end())
{
cout << ret->first << " " << ret->second << endl;
}
else
{
cout << "没有找到" << endl;
}
cout << "M.size() = " << M.size() << endl;
return 0;
}
3.2 Key为自定义数据类型
3.2.1 指定排序规则
对于Key为自定义数据类型必须指定排序规则,否则无法构造map容器,因为map容器所有元素都会根据元素的键值自动被排序
指定排序规则的的方法:
方法一:在自定义数据类型中重载 " < " [bool operator<()]
方法二:写一个仿函数,指定排序规则,在构造map容器时使用
#include <iostream>
#include <map>
using namespace std;
struct Key
{
int key1;
int key2;
int key3;
// 方法一
bool operator<(const Key& K) const
{
if (key1 == K.key1 && key2 == K.key2) // 如果key1和key2都相当,以key3进行升序排列
{
return key3 < K.key3;
}
else
{
if (key1 == K.key1) // 如果key1相等, 以key2进行升序排列
{
return key2 < K.key2;
}
else
{
return key1 < K.key1; // 都不相等, 以key1进行升序排列
}
}
}
};
// 方法二
class myCompare
{
public:
bool operator()(const Key& k1, const Key& k2)
{
if (k1.key1 == k2.key1 && k1.key2 == k2.key2) // 如果key1和key2都相当,以key3进行降序排列
{
return k1.key3 > k2.key3;
}
else
{
if (k1.key1 == k2.key1) // 如果key1相等, 以key2进行降序排列
{
return k1.key2 > k2.key2;
}
else
{
return k1.key1 > k2.key1; // 都不相等, 以key1进行降序排列
}
}
}
};
int main()
{
// 方法一的map的构造
map<Key, int> M;
// 方法二的map构造
//map<Key, int, myCompare> M;
Key k1;
k1.key1 = 10; k1.key2 = 20; k1.key3 = 30;
Key k2;
k2.key1 = 10; k2.key2 = 20; k2.key3 = 15;
Key k3;
k3.key1 = 10; k3.key2 = 15; k3.key3 = 15;
Key k4;
k4.key1 = 1; k4.key2 = 15; k4.key3 = 15;
M.insert(make_pair(k1, 1));
M.insert(make_pair(k2, 2));
M.insert(make_pair(k3, 3));
M.insert(make_pair(k4, 4));
// 方法一的打印
for (map<Key, int>::iterator it = M.begin(); it != M.end(); ++it)
{
cout << it->first.key1 << " "
<< it->first.key2 << " "
<< it->first.key2 << " "
<< it->second << endl;
}
// 方法二的打印
#if 0
for (map<Key, int, myCompare>::iterator it = M.begin(); it != M.end(); ++it)
{
cout << it->first.key1 << " "
<< it->first.key2 << " "
<< it->first.key2 << " "
<< it->second << endl;
}
#endif
return 0;
}
3.2.2 将自定义数据类型通过位域组成内置数据类型
#include <iostream>
#include <map>
using namespace std;
struct A
{
// 通过位域将下面三个字段组成一个uint64_t类型的数据
// 这样就不需要重载<号,或者使用仿函数指定排序规则了
uint64_t b1:36;
uint64_t b2:16;
uint64_t b3:12;
};
int main()
{
map<uint64_t, int> M;
A a1;
a1.b1 = 12345; a1.b2 = 12; a1.b3 = 10;
A a2;
a2.b1 = 1234; a2.b2 = 11; a2.b3 = 15;
A a3;
a3.b1 = 123; a3.b2 = 0; a3.b3 = 0;
M.insert(make_pair(*(uint64_t*)&a1, 1));
M.insert(make_pair(*(uint64_t*)&a2, 2));
M.insert(make_pair(*(uint64_t*)&a3, 3));
for (map<uint64_t, int>::iterator it = M.begin(); it != M.end(); ++it)
{
cout << it->second << endl;
}
return 0;
}