《C++ primer》(第5版) chapter11 读书笔记

11.1 使用关联容器
  • 关联容器支持高效的关键字查找和访问,两个主要的关联容器类型是mapset
  • 标准库提供8个关联容器,这8个容器的不同体现在三个维度上:
    • 是一个set,或是一个map
    • 要求不重复的关键字,或者允许重复关键字(允许重复关键字的容器名字汇总都有包含单词multi)
    • 按顺序保存元素,或无序保存(不保持关键字按照顺序存储的容器的名字都以单词unordered开头)
关联容器类型特征
map关联数组;保存关键字-值对
set关联字即值,即只保存关键字的容器
multimap关键字可重复出现的map
multiset关键字可重复出现的set
unordered_map用哈希函数组织的map
unordered_set用哈希函数组织的set
unordered_multimap哈希组织的map;关键字可以重复出现
unordered_multiset哈希组织的set;关键字可以重复出现
11.2 关联容器概述
  • 对于有序容器map,multimap,set,multiset,关键字类型必须定义元素比较的方法(见例子一)
//例子一
bool compareIsbn(const Sales_data &lhs,const Sales_data &rhs){
    return lhs.isbn()<rhs.isbn();
}
//bookstore中的元素以ISBN的顺序进行排列
multiset<Sales_data,decltype(compareIsbn)*> bookstore(compareIsbn);
11.3 关联容器操作
类型别名含义
key_type此容器类型的关键字类型
mapped_type每个关键字关联的类型;只适用于map
value_type对于set,与key_type相同;对于map,为pair<const key_type,mapped_type>
  • 当解引用一个关联容器的迭代器时,我们会得到一个value_type的值的引用(见例子一)
    • 对于map来说,value_typepair类型,其first成员保存const的关键字
  • 当使用一个迭代器遍历一个map,multimap,setmultiset时,迭代器按关键字升序遍历元素
  • 对于不包含重复关键字的容器的insert操作和emplace操作,返回一个pair
    • pairfirst成员是一个迭代器,指向具有给定关键字的元素
    • pairsecond成员是一个bool值,指出元素是插入成功还是已经存在于容器中(见例子三)
  • 对允许重复关键字的容器,接受单个元素的insert操作返回一个指向新元素的迭代器。
    • 这里无须返回一个bool值,因为insert总是向这类容器中加入一个新元素
  • 关联容器定义了三个版本的erase(见例子四)
  • 对一个map使用下标操作,其行为与数组或vector上的下标操作很不相同:
    • 使用一个不在容器中的关键字作为下标,会添加一个具有此关键字的元素到map
  • 如果一个multimapmultiset中有多个元素就有给定关键字,则这些元素在容器中会相邻存储,因为multimapmultiset都是有序的(见例子六)
//例子一

//统计每个单词在输入中出现的次数
map<string,size_t> word_count;
string word;
while(cin>>word)
    ++word_count[word];
auto map_it=word_count.cbegin();
//*map_it是指向一个pair<const stirng,size_t>对象的引用
while(map_it!=word_count.cend()){
    cout<<map_it->first<<" occurs "
        <<map_it->second<<" tiems "<<endl;
    ++map_it;                       //递增迭代器,移动到下一个元素
}

//例子二:关联容器的insert操作
c.insert(v)                         //v是value_type类型的对象;args用来构造一个元素
c.emplace(args)

c.insert(b,e)                       //b和e是迭代器,表示一个c::value_type类型值的范围;
c.insert(il)                        //il是表示c::value_type类型值的花括号列表

//例子三
//统计每个单词在输入中出现次数的一种更繁琐的方法
map<string,size_t> word_count;      //从string到size_t的空map
string word;
while(cin>>word){
    //若word已在word_count中,insert什么也不做
    auto ret=word_count.insert({word,1});
    if(!ret.second)                 //word已在word_count中
        ++ret.first->second;        //递增计数器
}

//例子四:从关联容器删除元素
c.erase(k)                          //从c中删除每个关键字k的元素
                                    //返回一个size_type的值,指出删除的元素的数量

c.erase(p)                          //从c中删除迭代器p指定的元素
                                    //返回一个指向p之后元素的迭代器

c.erase(b,e)                        //删除迭代器对b和e所表示的范围中的元素
                                    //返回e

//例子五:在一个关联容器中查找元素的操作
c.find(k)                           //返回一个迭代器,指向第一个关键字为k的元素,若k不在容器中,则返回尾后迭代器
c.count(k)                          //返回关键字等于k的元素的数量,对于不允许重复关键字的容器,返回值永远是0或1

//例子六
string search_item("Alain de Botton");          //要查找的作者
auto entries=authors.count(search_item);        //元素的数量
auto iter=authors.find(search_item);            //此作者的第一本书
//用一个循环查找此作者的所有著作
while(entries){
    cout<<iter->second<<endl;
    ++iter;                                     //前进到下一本书
    --entries;                                  //记录已经打印了多少本书
}

注意:在map中查找元素是否存在,使用find,而不是使用下标操作

11.4 无序容器
  • 无序容器在存储上组织为一组桶,每个桶保存零个或多个元素
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值