C++标准库之关联容器(C++ Primer)

本文深入解析了STL中的关联容器和无序容器,包括map、multimap、set、multiset以及unordered_map、unordered_set等的实现原理、初始化方式、关键字类型要求及容器操作。详细介绍了红黑树和哈希技术在容器中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、关联容器

map\multimap  set\multiset  关联容器是通过红黑树来实现的。
1、关联容器的初始化
  • 默认初始化
  • 拷贝初始化(或者为一个容器的迭代器区间)
  • 初始化列表初始化
2、关键字类型的要求
  • 关键字类型定义一个“行为正常”的<运算符;
  • 通过制定行为正常的comp函数:multiset<Sales_data, decltype(compareIsbn)*> bookstore(compareIsbn);
3、pair类型

定义在utility头文件中,含有first和second两个public数据成员

  • 初始化
    pair<T1,T2> p; //默认初始化
    pair<T1,T2> p(v1,v2); pair<T1,T2> p = {v1,v2}; //用v1,v2分别初始化first和second成员
    pair<T1,T2> p = make_pair(v1,v2);
  • p.first和p.second返回 p中第一个和第二个数据成员;即数据成员是public的
  • 关系运算:先比较first,在first相等的情况下,再比较second,得出最终的关系
4、关联容器的操作
4.1 关联容器额外的类型别名
  • key_type //关键字类型
  • mapped_type //map专有,map中pair的second成员类型
  • value_type //map的value_type是一个pair,我们可以改变pair的值但不能改变关键字成员的值;set的value_type就是key_type
  • set的迭代器是const的。
  • 我们通常不对关联容器使用泛型算法;在实际编程中,如果我们对一个关联容器使用算法,要么把它当做一个源序列,要么当做一个目的序列
  • 关联容器支持begin和end;关联容器中的数据是按照关键字升序排列的
4.2 添加元素
  • c.insert(v);
  • c.emplace(args);
  • c.insert(beg, end);
  • c.insert(il);
  • c.insert(p,v);
  • c.emplace(p,v);
    添加单一元素的insert和emplace返回一个pair;pair的first成员是一个迭代器,指向给定关键字的元素;second成员是一个bool,指出是否插入成功。
4.3 删除元素
  • c.erase§; c.erase(b,e); //这是容器通用版本,返回删除元素后的位置
  • c.erase(k); //k是key_type,返回删除的元素的数量
4.4 map的下标操作
返回类型是map_type的引用。
  • 使用一个不在容器中关键字作为下标,会添加一个具有此关键字的元素到map中。
  • c.at(k); //与顺序容器中的行为一致。
4.5 访问元素
lower_bound和upper_bound不适用于无序容器
  • c.find(k); //返回一个迭代器,指向第一个关键字为k的元素
  • c.count(k); //返回关键字为k的元素的数量
  • c.lower_bound(k); //返回一个迭代器,指向第一个关键字不小于k的元素
  • c.upper_bound(k); //返回一个迭代器,指向第一个关键字大于k的元素
  • c.equal_bound(k); //返回一个迭代器pair,表示关键字等于k的集合
  • lower_bound返回的迭代器可能指向一个具有给定关键字的元素,但也可能不指向。如果关键字不在容器中,则low_bound会返回关键字的第一个安全插入点——不影响容器中元素顺序的插入点。如果low_bound和upper_bound返回相同的迭代器,则给定关键字不在容器中。

二、无序容器

unordered_map\unordered_multimap  unordered_set\unordered_multiset

1 如果关键字类型固有就是无序的,或者性能测试发现问题可以用哈希技术解决,就可以使用无序容器。
2 无序容器在存储上组织为一组桶,每个桶有零个或多个元素。无序容器使用一个哈希函数将元素映射到桶。也就是使桶的容量大于等于冲突元素的数量,一个桶可能容纳几个哈希值的元素

1、无序容器的管理操作
(1)、桶接口
  • c.bucket_count(); //正在使用的桶的数目
  • c.max_bucket_count(); //容器能容纳的最多的桶的数量
  • c.bucket_size(n); //第n个桶中有多少个元素
  • c.bucket(k); //关键字为k的元素在哪个桶中
(2)、桶迭代
  • local_iterator //可以用来访问桶中元素的迭代器类型
  • const_local_iterator //const版本
  • c.begin(n),c.end(n);
  • c.cbegin(n), c.cend(n); //返回桶n的首元素迭代器和尾后迭代器
(3)、哈希策略
  • c.load_factor(); //每个桶平均元素数量,返回float值
  • c.max_load_factor(); //c试图维护的平均桶大小,返回float值。c会在需要时添加新桶,以使得load_factor <= max_load_factor
  • c.rehash(n); //重组存储,使得bucket_count >= n且bucket_count > size / max_load_factor
  • c.reserve(n); //重组存储,使得c可以保存n个元素且不必rehash
2、无序容器对关键字类型的要求
  • 无序容器使用关键字类型的==运算符来比较元素
  • 使用一个 hash<key_type> 类型的对象来生成每一个元素的哈希值。
  • 标准库为内置类型(包括指针)、string类型、智能指针类型提供了hash模板。
//定义Sales_data类型的哈希函数
		size_t hasher(const Sales_data &sd)
		{
		    return std::hash<std::string>()(sd.isbn());
		}
		
		//定义Sales_data类型的相等性判断运算符函数
		bool eqOp(const Sales_data &lhs, const Sales_data &rhs)
		{
   			 return lhs.isbn() == rhs.isbn();
		}

		//无序容器类型要指明元素类型、哈希函数类型,相等性判定函数类型
		using SD_multiset = std::unordered_multiset<Sales_data, decltype(hasher)*, decltype(eqOp)*>;
		//无序容器的初始化,指明桶大小、哈希函数指针、相等性判定运算符指针
		SD_multiset bookstore(42, hasher, eqOp);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值