• 关联容器


    [0. 概述]

    关联容器和顺序容器的本质差别在于:

    关联容器通过键(key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素。

    虽然关联容器的大部分行为与顺序容器相同,但其独特之处在于支持键的使用。
    关联容器(Associative containers)支持通过键来高效地查找和读取元素。

    两个基本的关联容器类型是 map 和 set。
    map 的元素以键-值(key-value)对的形式组织:
    key 用作元素在 map 中的索引,而 value 则表示所存储和读取的数据。
    set 仅包含一个键,并有效地支持关于某个键是否存在的查询。

    一般来说,如果希望有效地存储不同值的集合,那么使用 set 容器比较合适,
    而 map 容器则更适用于需要存储(乃至修改)每个键所关联的值的情况。
    在做某种文本处理时,可使用 set 保存要忽略的单词。
    而字典则是 map 的一种很好的应用:单词本身是键,而它的解释说明则是值。
    set 和 map 类型的对象所包含的元素都具有不同的键,不允许为同一个键添加第二个元素。
    如果一个键必须对应多个实例,则需使用 multimap 或 multi set,这两种类型允许多个元素拥有相同的键。

    关联容器支持很多顺序容器也提供的相同操作,此外,还提供管理或使用键的特殊操作。

    // 表 10.1. 关联容器类型
    map       关联数组:元素通过键来存储和读取
    
    set       大小可变的集合,支持通过键实现的快速读取
    
    multimap    支持同一个键多次出现的 map 类型
    
    multiset    支持同一个键多次出现的 set 类型

    [1. 引言:pair 类型]

    在开始介绍关联容器之前,必须先了解一种与之相关的简单的标准库类型:
    pair(表 10.2),该类型在 utility 头文件中定义。

    // 表 10.2 pairs 类型提供的操作
    pair<T1, T2> p1;         创建一个空的 pair 对象,它的两个元素分别是 T1 和 T2 类型。
    
    pair<T1, T2> p1(v1, v2);    创建一个 pair 对象,它的两个元素分别是 T1 和 T2 ,
                      其中 first 成员初始化为 v1,而 second 成员初始化为 v2
    
    make_pair(v1, v2);          以 v1 和 v2 值创建一个新 pair 对象,其元素类型分别是 v1 和 v2 的类型
    
    p1 < p2                     两个 pair 对象之间的小于运算,其定义遵循字典次序:
                    如果 p1.first < p2.first 
                    或 !(p2.first < p1.first) && p1.second < p2.second,则返回 true
    
    p1 == p2             如果两个 pair 对象的 first 和 second 成员依次相等,则这两个对象相等。
                    该运算使用其元素的 == 操作符
    
    p.first              返回 p 中名为 first 的(公有)数据成员
    
    p.second              返回 p 的名为 second 的(公有)数据成员

    1.1 pair 的创建和初始化

    pair 包含两个数据值。与容器一样,pair 也是一种模板类型。
    z注意,在创建 pair 对象时,必须提供两个类型名:
    pair 对象所包含的两个数据成员各自对应的类型名字,这两个类型不必相同。

    pair<string, string> anon; // holds two strings
    pair<string, int> word_count; // holds a string and an int
    pair<string, vector<int> > line; // holds string and vector<int>

    如果在创建 pair 对象时不提供初始化式,则调用默认构造函数对其成员采用值初始化。
    当然,也可在定义时为每个成员提供初始化式:

    pair<string, string> author("James", "Joyce");

    如果需要定义多个相同的 pair 类型对象,可考虑利用 typedef 简化其声明:

    typedef pair<string, string> Author;
    Author proust("Marcel", "Proust");
    Author joyce("James", "Joyce");

    1.2 pairs 对象的操作

    与其他标准库类型不同,对于 pair 类,可以直接访问其数据成员:
    其成员都是 public 的,分别命名为 first 和 second。
    只需使用普通的点操作符即可:

    string firstBook;
    // access and test the data members of the pair
    if (author.first == "James" && author.second == "Joyce")
    firstBook = "Stephen Hero";

    标准库只为 pair 类型定义了表 10.2 所列出的数量有限的操作。

    1.3 生成新的 pair 对象

    除了构造函数,标准库还定义了一个 make_pair 函数,
    由传递给它的两个实参生成一个新的 pair 对象。
    可使用如下函数创建新的 pair 对象,并赋给已存在的 pair 对象:

    pair<string, string> next_auth;
    string first, last;
    while (cin >> first >> last) {
      // generate a pair from first and last
      next_auth = make_pair(first, last);
      // process next_auth...
    }

    在 while 循环条件中读入的作者名字作为实参,
    调用 make_pair 函数生成一个新的 pair 对象。
    此操作等价于下面更复杂的操作:

    // use pair constructor to make first and last into a pair
    next_auth = pair<string, string>(first, last);

    由于 pair 的数据成员是公有的,因而可如下直接地读取输入:

    pair<string, string> next_auth;
    // read directly into the members of next_auth
    while (cin >> next_auth.first >> next_auth.second) {
      // process next_auth...
    }


    [2. 关联容器]
    关联容器共享大部分的顺序容器操作。但是,关联容器不提供 ——
    front、 push_front、 pop_front、back、push_back 以及 pop_back 操作。

    顺序容器和关联容器公共的操作包括下面的几种:

    1. 构造函数:
      C<T> c; // creates an empty container
      // c2 must be same type as c1
      C<T> c1(c2); // copies elements from c2 into c1
      // b and e are iterators denoting a sequence
      C<T> c(b, e); // copies elements from the sequence into c
      "注意 "—— 关联容器不能通过容器大小来定义,因为这样的话就无法知道键所对应的值是什么。
    
    2. 关系运算。
    
    3. begin、end 操作。
      c.begin(); c.end(); c.rbegin(); c.rend()。
    
    4. 类型别名 typedef :
      (size_type, iterator, const_iterator,reverse_iterator, const_reverse_iterator, 
      difference_type, value_type, reference, const_referenc )
      注意,对于 map 容器,value_type 并非元素的类型,而是描述键及其关联值类型的 pair 类型。
      以后将详细解释 map 中的类型别名。
    
    5. 赋值操作。
      c1 = c2; c1.swap(c2);
    
    6. clear 和 erase 操作。
      c.erase(p); c.erase(b, e); c.clear();
    
    7. 容器大小的操作。
      c.size(); c.max_size(); c.empty();
    
    8. 根据键排列元素

    除了上述列出的操作之外,关联容器还提供了其他的操作。

    对于顺序容器也提供的相同操作,关联容器也重新定义了这些操作的含义或返回类型,
    其中的差别在于关联容器中使用了键 ——
    " 关联容器的元素根据键的次序排列" 这一事实就是一个重要的结论:
    在迭代遍历关联容器时,我们可确保按键的顺序的访问元素,而与元素在容器中的存放位置完全无关。

  • 相关阅读:
    Android拍照+方形剪裁——附代码与效果图
    Caffe源代码中Solver文件分析
    Java学习笔记五(多线程)
    setTimeout和setInterval的区别
    javascript中this的妙用
    javascript基于原型的语言的特点
    css样式小技巧
    html块元素和内联元素
    怎么解决浏览器兼容性问题
    高效率、简洁、CSS代码优化原则
  • 原文地址:https://www.cnblogs.com/yshl-dragon/p/3140592.html
Copyright © 2020-2023  润新知