c++ primer第五版----学习笔记(十一)Ⅰ

1.关联容器

  • 关联容器的种类:
//有序关联容器:按关键字有序保存元素
map                       //保存关键字-值对
set                       //只保存关键字,即值
multimap                  //关键字可重复出现的map
multiset                  //关键字可重复出现的set
//类型map和multimap定义在头文件map中;set和multiset定义在头文件set中

//无序关联容器:使用哈希函数组织元素
unordered_map               //用哈希函数组织的map
unordered_set               //用哈希函数组织的set
unordered_multimap          //用哈希函数组织的map;关键字可重复出现
unordered_multiset          //用哈希函数组织的set;关键字可重复出现

  • 定义和初始化关联容器:
//定义一个map时,必须指明关键字类型与值类型
map<string, size_t> word_count;   //关键字类型是string,值类型是size_t
//定义一个set时,只需指明关键字类型
set<string> exclude;  //关键字类型是string

/*初始化关联容器:1.可以将关联容器初始化为另一个同类型容器的拷贝
2.从一个值范围来初始化关联容器
3.当初始化multimap或multiset时,重复关键字不会被剔除
*/


2.关键字类型的要求

  • 对于有序容器,关键字类型必须定义元素比较的方法
  • 在集合类型中,关键字类型就是元素类型;在映射类型中,关键字类型是元素的第一部分的类型
  • 在实际编程中,如果一个类型定义了“行为正常”的<运算符,则它可以用作关键字类型

3.pair类型

  • 定义在utility头文件中
  • 一个pair包含两个数据成员;当创建一个pair时,必须提供两个类型名;map的元素即为pair
  • pair上的相关操作:
pair<T1,T2> p;                   //p是一个pair,两成员都进行了值初始化
pair<T1,T2> p(v1, v2)            //first和second成员分别用v1和v2进行初始化
pair<T1,T2> p = {v1, v2};        //等价于p(v1, v2)
make_pair(v1, v2)                //返回一个用v1 和v2初始化的pair
p.first    
p.second
p1 relop p2                     //关系运算符(<,>、<=、>=)按字典序定义
p1 == p2                        //当first和second成员分别相等时,两个pair相等
p1 != p2

4.关联容器操作

  • 关联容器额外的类型别名:
key_type            //关键字类型
mapped_type         //关键字关联到的类型
value_type          //对于set,与key_type相同;对于map,为pair<const key_type, mapped_type>
  • 关联容器迭代器:
//1.当解引用一个关联容器迭代器时,得到一个类型为容器的value_type的值的引用

//2.对map而言,value_type是一个pair类型,first成员保存const的关键字,second成员保存值

auto map_it = word_count.begin();
//*map_it是指向一个pair<sonst string, size_t>对象的引用

//3.set的迭代器是const的,即只能用set迭代器读取元素的值而不能修改

//4.当使用一个迭代器遍历一个map、multimap、set或multiset时,迭代器按关键字升序遍历元素

//5.关联容器可用于只读取元素的算法
  • 添加元素:
//关联容器insert操作
c.insert(v)         
c.emplace(args) 
                     /*v是一个value_type类型的对象;对于map和set,只有当元素的关键字不在c时
                     才插入,函数返回一个pair,为pair<iterator, bool>,bool值为指示插入是否
                     成功;对于multimap和multiset,总会插入(或构造)给定元素,并返回一个指向
                     新元素的迭代器*/
c.insert(b, e)
c.insert(il)
c.insert(p, v)       //迭代器p作为一个提示,指出从哪里开始搜索新元素应该存储的位置
c.emplace(p, args)   //返回一个迭代器,指向具有给定关键字的元素
                      

//检测insert的返回值
/*使用insert返回的pair的first成员是一个迭代器,指向具有给定关键字的元素;second成员是一个bool值,指出元素是否插入成功;1.若关键字已在容器中,则insert什么事情也不做,且bool值为false,2.若关键字存在,则元素被插入到容器中,且bool值为true*/

//对允许重复关键字的容器,接受单个元素的insert操作返回一个指向新元素的迭代器,不须返回bool

  • 删除元素:
//从关联容器删除元素
c.erase(k)        //从c中删除关键字为k的元素;返回一个size_type值,指出删除的元素的数量
c.erase(p)        //从c中删除迭代器p指定的元素;返回一个指向p之后元素的迭代器
c.erase(b, e)     //删除迭代器对b和e所表示的范围中的元素,返回e

//对于保存不重复关键字的容器,erase的返回值总是0huo1;若返回值为0,则表明想要删除的元素并不在容器中
  • map的下标操作:
c[k]          //返回关键字为k的元素;如果k不在c中,添加一个关键字为k的元素,并对其进行值初始化
c.at(k)       //访问关键字为k的元素,带参数检查;若k不在c中,抛出一个out_of_range异常
//对一个map进行下标操作,会获得一个mapped_type对象
  • 访问元素:
//lower_bound和upper_bound不适用于无序容器
//下标和at操作只适用于非const的map和unordered_map
c.find(k)             //返回一个迭代器,指向第一个关键字为k的元素;若k不在容器中,则返回尾后迭代器
c.count(k)            //返回关键字等于k的元素的数量;对于不允许重复关键字的容器,返回值永远是0或1
c.lower_bound(k)      //返回一个迭代器,指向第一个关键字不小于k的元素
c.upper_bound(k)      //返回一个迭代器,指向第一个关键字大于k的元素
c.equal_range(k)     //返回一个pair,表示关键字等于k的元素的范围;若k不存在,pair的两个成员军等于c.end()

//如果lower_bound和upper_bound返回相同的迭代器,则给定关键字不在容器中

5.无序容器:使用一个哈希函数和关键字类型的==运算符

  • 如果关键字类型固有就是无序的,或者性能测试发现问题可以用哈希技术解决,就可以使用无序容器
  • 无序容器在存储组织上为一组桶,每个桶保存0个或多个元素;无序容器使用一个哈希函数将元素映射到桶
  • 无序容器管理操作:
//桶接口
c.bucket_count()                //正在使用的桶数目
c.max_bucket_count()            //容器能容纳的最多的桶的数量
c.bucket_size(n)                //第n个桶中有多少个元素
c.bucket(k)                     //关键字为k的元素在哪个桶中
//桶迭代
local_iterator                  //可以用来访问桶中元素的迭代器类型
const_local_iterator            //const版本
c.begin(n), c.end(n)            //桶n的首元素迭代器和尾后迭代器
c.cbegin(n), c.cend(n)         //返回const_local_iterator
//哈希策略
c.load_factor()                 //每个桶的平均元素数量,返回float值
c.max_load_factor()             //c试图维护的平均桶大小
c.rehash(n)               //重组存储,使得bucket_count>=n且bucket_count>size/max_load_factor
c.reserve(n)              //重组存储,使得c可以保存n个元素且不必rehash
  • 无序容器对关键字类型的要求:类似于为有序容器提供比较操作,我们需要为无序容器提供hash值计算函数和相等判断函数
size_t hasher(const Sales_data &sd)
{
    return hash<string>()(sd.isbn());
}

bool eqOp(const Sales_data &lhs, const Sales_data &rhs)
{
    return lhs.isbn() == rhs.isbn();
}

using SD_multiset = unordered_multiset<Sales_data, decltype(hasher) *, decltype(eqOp) *>;
SD_multiset bookstore(42, hasher, eqOp);

 

--------------------------------------------------------------------2018.12.16日再更新--------------------------------------------------------

map插入的三种方式:

//pair---> utility头文件
map<int, string> mapStudent;
//pair<--insert
mapStudent.insert(pair<int, string>(1, "student_one"));
//value_type<--insert
mapStudent.insert(map<int, string>::value_type (1, "student_ont"));
//mp[]<--数组下标
mapStudent[1] = "student_ont";

检查是否插入成功:

pair<map<int, string>::iterator, bool> insert_pair;
insert_pair = mapStudent.insert(pair<int, string>(1, "student_one"));
//插入成功则insert_pair.second为true,否则为false

遍历map的三种方式:

1. 前向迭代器

2. 反向迭代器

3. 数组方式

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值