C++ primer 第11章 关联容器 小结

        引子1:关联容器和顺序容器有着根本的不同:关联容器中的元素是按关键字来保存和访问的。而顺序容器中的元素是按它们在容器中的位置来顺序保存和访问的。不同之处反映了关键字的作用。

        引子2 :两个主要的关联容器(associative_container)类型是map和set。map中的元素是一些关键字—值(key-value)对:关键字起到索引的作用,值则表示与索引相关联的数据。set中的每个元素只包含一个关键字;set支持高效的关键字查询操作——检查一个给定关键字是否在set中。

         引子3:标准库提:8个关联容器,它们的不同体现在三个维度上:(1)或者是一个map,或者是一个set。(2)或者要求不重复的关键字,或者要求重复(multi_)关键字;(3)按顺序保存元素,或无序(unordered_)保存。类型map和multimap定义在头文件map中;set和multiset定义在头文件set中;无序容器则定义在头文件unordered_map和unordered_set中。

         1、使用关联容器

         1.1map的使用

          map类型通常被称为关联数组。关联数组与“正常”的数组类似,不同之处在于其下标不必是整数。我们通过一个关键字而不是位置查找值。给定一个名字到电话号码的map,我们可以使用一个人的名字作为下标来获取此人的电话号码。

          经典例:单词计数程序

map<string, size_t> word_count;//string到size_t的空map
string word;
while(cin >> word)
    ++word_count[word];        //提取word的计数器并将其加1
for(const auto &w : word_count)  //对map中的每个元素打印结果
     cout << w.first << "occurs" >> w.second
          << ((w.sevond > 1) ? "times" : "time") << endl;

    此程序读取输入,报告每个单词出现多少次。

       为了定义一个map,我们必须指定关键字和值的类型。在此程序中,map保存每个元素中,关键字是string类型,值是size_t类型。当对word_count进行下标操作时,我们使用一个string作为下标,获得与此string相关联的size_t类型的计数器。while循环每次从标准输入读取一个单词。它使用每个单词对word_count进行下标操作。如果word还未在map中,下标运算符会创建一个新元素,其关键字为word,值为0。不管元素是否是新创建的,我们将其值加1。一旦读取完所有的输入,范围for语句就会遍历map,打印每个单词和对应的计数器。当从map中提取一个元素时,会得到一个pair类型的对象。pair是一个模板类型,保存两个名为first 和second的(公有)数据成员。map所使用的pair用first成员保存关键字,用second成员保存对应的值。

       1.2set的使用

        与之相对,set就是关键字的简单集合。当只是想知道一个值是否存在时,set是最有用的。

        上一程序的扩展:忽略常见单词,如“the”、“and”、“or”等。可以使用set保存想忽略的单词。

         

map<string, size_t> word_count;//string到size_t的空map
set<string> exclude = {"The", "But","And","Or","An","A",
                        "the","but","and","or","an", "a"};

string word;
while(cin >> word)
if(exclude.find(word) == exclude.end())
    ++word_count[word];        //提取word的计数器并将其加1
for(const auto &w : word_count)  //对map中的每个元素打印结果
     cout << w.first << "occurs" >> w.second
          << ((w.sevond > 1) ? "times" : "time") << endl;

     与顺序容器类似,可以对一个关联容器的元素进行列表初始化。

     if(exclude.find(word) == exclude.end()) //只统计不在exclude中的单词

     find调用返回一个迭代器。如果给定关键字在set中,迭代器指向关键字。否则,ffind返回尾后迭代器。

    2、关联容器概述

        关联容器不支持顺序容器的位置相关操作。也不支持构造函数或插入操作这些接受一个元素值和一个数量值的操作。关联容器的迭代器都是双向的。

    2.1定义关联容器

        当定义一个map时,必须既指明关键字类型又指明值类型;我们将每个关键字-值对包含在花括号中:{key,value}来指出它们一起构成了map1中的一个元素;而定义一个set时,只需指明关键字类型。

       初始化multimap或multiset。 一个map或set中的关键字必须是唯一的,即,对于一个给定的关键字,只能有一个元素的关键字等于它。容器multimap和multiset没有此限制,它们允许多个元素具有相同的关键字。

   2.2关键字类型的要求

        对于有序容器——map、multimap、set和multiset,关键字类型必须定义元素的比较方法。默认情况下,标准库使用关键字类型的<运算符来比较两个关键字。传递给排序算法的可调用对象(谓词)必须满足与关联容器中的关键字一样的类型要求。可以向一个算法提供我们自己定义的比较操作,与之类似,也可以提供自己定义的操作来代替关键字上的<运算符。所提供的操作必须在关键字类型上定义一个严格弱序。可以将严格弱序看作“小于等于”,虽然实际定义的操作可能是一个复杂的函数。在实际编程中,重要的是,如果一个类型定义了“行为正常”的<运算符,则它可以用作关键字类型。

         我们不能直接定义一个Sales_data的multiset,因为Sales_data没有<运算符。可以用compareIsbn函数来定义一个multiset。

此函数在Sales_data对象的ISBN成员上定义了一个严格弱序。定义如下:

bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs)
{

     return lhs.isbn() < rhs.isbn();

}


//bookstore中多条记录可以有相同的ISBN
//bookstore中的元素以ISBN的顺序进行排列


multiset<Sales_data, decltype(compareIsbn)*>
bookstore(compareIsbn);

     在定义multiset时必须提供两个类型:关键字类型Sales_data,以及比较操作类型——应该是一种函数指针类型,可以指向compareIsbn。

       此处,使用了decltype来指出自定义操作类型。当用decltype来获得一个函数指针类型时,必须加上一个*来指出我们要使用一个给定的函数类型的指针。用compareIsbn来初始化bookstore对象,这表示我们向bookstore添加元素时,通过调用compareIsbn来为这些元素排序。可以用compareIsbn代替&compareIsbn作为构造函数的参数,因为当我们使用一个函数名字时,在需要的情况下它会自动转化为一个指针。

        2.3pair

         pair是标准库类型,定义在头文件utility中。与其他标准库类型不同,pair的数据成员是public的。两个成员分别命名为first和second。可以用普通的成员访问符号访问它们。

       

pair<T1, T2> p(v1, v2);
//等价
pair<T1, T2> p = {v1, v2};
//等价
make_pair(v1, v2);

 
p.first ;     //返回p的名为first的(公有)数据成员
p.second;     //返回p的名为second的(公有)数据成员

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值