map和multimap的特点: 通常底层是由平衡二叉树完成。将key和value组成的pair对组当成元素,根据元素的key进行排序,这么一来根据已知的key搜寻元素就能有很好的性能。这一性质也使得你不可以直接改动元素的key,因为这会打乱正确的次序。使用容器时应包含头文件map,打开命名空间std。
map和multimap的不同之处: map不可以放相同key的元素,multimap可以。
map和multimap的迭代器: 双向迭代器
map和multimap的初始化
template<class Key,class T,class Compare= less<Key>,class Allocator = allocator<pair<const Key,T>>>
class map;
template<class Key,class T,class Compare= less<Key>,class Allocator = allocator<pair<const Key,T>>>
class multimap;
//第一模板参数为元素的key类型
//第二模板参数为元素的value类型
//第三参数为排序准则 默认为less<>
//第四参数为内存模型,默认为allocator,由c++标准库提供
//一般初始化只需要指定前两个模板参数
map<T1,T2>c1;
map<T1,T2>c2(c1);
map<T1,T2>c3(iterator1,iterator2);
//列表初始化方法其中t1,t2为T1,T2的对象
map<T1,T2>c4={ make_pair(t1,t2),make_pair(t1,t2)};
c.~map();
//multimap同上
for (auto e : c1) //循环遍历---c1为容器对象
{
cout << e.first << " " << e.second << endl;
}
非变动性操作函数 | 效果 |
---|---|
c.size() | 返回容器的大小 |
c.empty() | 判断容器是否为空 |
c.max_size() | 返回可容纳的最大元素数量(一般不用) |
c1==c2 | |
c1!=c2 | |
c1<c2 | |
c1>c2 | |
c1<=c2 | |
c1>=c2 |
比较操作以字典顺序来比较,比较只能用于模板参数类型都一样的容器。
特有的搜寻函数 | 功能 |
---|---|
c.count(key) | 返回c容器中键值为key的个数 |
c,find(key) | 返回指向c容器中键值为key的第一个元素的迭代器,找不到就返回end() |
c.lower-bound(key) | 返回第一个大于等于key值的元素位置的迭代器 |
c.upper_bound(key) | 返回第一个大于key值的元素位置的迭代器 |
c.equal_range(key) | 返回第一个大于等于key值的元素位置的迭代器,和大于key的迭代器,返回类型为pair将两个迭代器组合 |
赋值操作 | 功能 |
---|---|
c1=c2 | 将c2的所有元素的副本添加到c1 |
c1.swap(c2) | 交换c1,c3的所有元素 |
swap(c1,c2) | 效果同上,但效率不好,应该该版本是泛化版本 |
迭代器函数 | 效果 |
---|---|
c.begin() | 返回一个双向迭代器,指向第一个元素 |
c.end() | 返回一个双向迭代器,指向最后一个元素的下一位置 |
c.rbegin() | 返回一个逆向迭代器,指向逆向遍历的第一个元素 |
c.rend() | 返回一个逆向迭代器,指向逆向遍历的最后一个元素的下一位置 |
这里的迭代器是双向迭代器,所以对于只能用于随机存取迭代器的STL算法,map和multimap无福消受。
map和multimap的安插,移除操作函数 | 效果 |
---|---|
c.insert(make_pair(t1,t2)) | 安插元素的副本,如果c为map,返回一个pair<>将iterator和bool组合在一起的类型的对象,其中第一个参数指向插入元素,第二参数返回是否插入成功,multimap则返回一个指向插入元素的iterator |
c.insert(iterator,elem) | 效果同上,iterator为提示插入位置,若有效可以大大减少插入时间,返回指向插入元素的iterator |
c.insert(iterator1,iterator2) | 将区间[)内容副本插入c中,无返回值 ,若插入的key在原容器中已有,插入无效 |
c.erase(elem) | 移除所有与elem相等的元素返回被移除元素的个数,返回类型 map<>::size_type |
c.erase(iterator) | 移除迭代器指向位置的元素,返回指向下一元素的迭代器 |
c.erase(iterator1,iterator2) | 移除区间[iterator1,iterator2)移除区间内所有元素,返回iterator2迭代器 |
c.clear() | 将容器清空 |
如果要改变value的key只有一条路,那就是重新添加一个value一样的元素,把旧元素删除,map提供的一种便捷方法如下
int main()
{
//将第二个元素的key改为5
map<int, string>c1 =
{ make_pair(1,"罗斯"),make_pair(2,"纳什"),
make_pair(3,"艾弗森"),make_pair(4,"吉诺比利") };
for (auto e : c1) //输出改变前的容器内容
{
cout << e.first << " " << e.second << endl;
}
cout << endl;
c1[5] = c1[2];
c1.erase(2);
for (auto e : c1)//输出改变后的容器内容
{
cout << e.first << " " << e.second << endl;
}
}
安插元素常用的三种方法
map<int, string>c;
c.insert(map<int,string>::value_type(1,"罗斯"));
//value_type = pair<int,string>,等价于下面的写法
c.insert(pair<int, string>(2, "欧文"));
c.insert(make_pair(3,"艾弗森"));//最常使用,用make_pair模板参数推断
for (auto e : c)
{
cout << e.first << " " << e.second << endl;
}
c.erase(key)会删除容器内所有和key值相同的元素,那如果我们要删除multimap中第一个和key相同的元素如何做呢?
multimap<int, string>c2 =
{ make_pair(1,"罗杰"),make_pair(2,"路飞"),make_pair(2,"罗斯")};
for (auto e : c2) //输出删除前
{
cout << e.first << " " << e.second << endl;
}cout << endl;
auto itc2=c2.find(2); //返回指向第一个值为key元素的迭代器
c2.erase(itc2); //删除迭代器指向的元素
for (auto e : c2)//输出删除后
{
cout << e.first << " " << e.second << endl;
}cout << endl;
//注意!注意!!! 对itc2实施了erase()后,会使其失效
//如果我们再操作它会导致为定义行为。
//正确的删除方法 c2.erase(itc2++) 将迭代器往前,利用后置++返回的副本去删除
//同理,删除value元素
map<int,string>::iterator pos=c.begin();
while(pos!=c.end())
{
if(pos->second == value)
{
c.erase(pos++);
break;
}
else
++pos;
}
map的直接元素存取 | 功能 |
---|---|
c[key] | 返回一个referrence,指向键值为key元素的位置。如果该元素不存在,会直接创建,value为其类型默认构造函数决定 |
map通过下标直接存取的优点和缺点:
优点是:你可以方便的对着map安插新元素,以及前面提到的修改value的key。
缺点是:你可能会不小心创建了新元素,而你并不想要安插这个元素。