C++STL容器篇map和multimap

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。
缺点是:你可能会不小心创建了新元素,而你并不想要安插这个元素。

原创文章 23 获赞 1 访问量 366

猜你喜欢

转载自blog.csdn.net/weixin_44806268/article/details/105612453