一、关联容器

C++的容器类型可以分为顺序容器和关联容器两大类。对于关联容器,主要有map和set,对于这两种,根据不同的维度,衍生出了8种容器

map                                      //值对

set                                         //仅有值

multimap                               //允许关键字重复的值对

multiset                                 //允许重复的值

unordermap                          //无序值对

unorderset                             //无序值

unordermultimap                   //无序值对,允许关键字重复

unordermultiset                      //无序值,允许重复

二、pair类型

  在开始介绍关联容器之前,我们需要了解一种与之相关的标准库类型——pair类型,该类型定义在头文件utilty中。下表是pair类型提供的操作

  1. pair<T1,T2> p1; 创建一个空的pair对象,它的两个元素分别是T1T2类型,采用值初始化
  2. pair<T1,T2> p1(v1,v2); 创建一个pair对象,它的两个元素分别是T1T2类型,其中first成员初始化为v2second成员初始化为v2
  3. make_pair(v1,v2) v1,v2值创建一个新的pair对象,其元素类型分别是v1v2类型
  4. p1<p2 两个pair对象之间的小于运算,遵循字典顺序
  5. p1==p2 如果两个pair对象的firstsecond值依次相等,则它们相等
  6. p.first 返回p中名为first的数据成员
  7. p.second 返回p中名为second的数据成员

和容器一样,pair也是一种模板类型。它的数据成员是公有的,分别命名为first和second,只需点操作就可以访问其成员。其定义初始化的操作也很简单,除了构造函数外,pair还提供了一个make_pair函数来创建pair对象,并赋值给已存在的pair对象。

  1. pair<string,string> next_auth;
  2. string first,last;
  3. while(cin>>first>>last)
  4. next_auth=make_pair(first,last);
  5. 等价于
  6. next_auth=pair<string,string>(first,last);

三、map类型

 map是键-值对的集合。map类型可以理解为关联数组:可以使用键作为下标来获取一个值,正如内置数组类型一样。map和set等关联容器共享大部分顺序容器的操作。关联容器不提供front、push_front、pop_front、back、push_back和pop_back操作。

1.map对象的定义

  在使用map对象之前,需要在头文件中包含map头。其定义示例如下:

  1. #include<map>
  2. map<string,int> word_count;

  此外,map还共有3种构造函数用于定义和初始化。

  1. map<k,v> m; 创建一个名为m的空map对象,其键和值类型分别为kv类型
  2. map<k,v> m(m2); 创建一个m2的副本mmm2必须要有相同的键和值类型
  3. map<k,v> m(b,e); 创建map类型的对象m,存储迭代器be标记范围内所有元素的副本。元素的类型必须能转换位pair<const k,v>

  

2.map定义的类型

  由于map对象的元素是键-值对,即每个元素包含两个部分:键以及由键关联的值。vaule_type是存储元素的键以及值得pair类型,而且键位const。下表为map类定义的类型。

  1. map<K,V>::key_type map容器中,用作索引的键的类型
  2. map<K,V>::mapped_type map容器中,键所关联的值的类型
  3. map<K,V>::value_type 一个pair类型。它的first元素具有const map<K,V>::key_type 类型,而second元素具有map<K,V>::mapped_type类型

  注意对map迭代器进行解引用将产生的是pair类型的对象,它的first成员存放的是键,为const,second成员存放的是值。

3.map中添加元素

  给map添加元素有两种方式:一是使用insert成员实现。二是先用下标获取元素,让然后给获取的元素赋值。

  map使用下标和vector类似,返回的都是下标关联的值,但是map的下标是键而不是递增的数字。下面的程序很好的说明了这个特点。

  1. map<string,int> word_count;
  2. word_count["Anna"]=1;

  首先在word_count中查找键为Anna的元素,没有找到。接着将一个新的键-值对插入到word_count容器中,键为Anna,值初始化为0;最后会把值1赋值给键为Anna的元素。我们可以看到,用下标访问map中不存在的元素,会导致在map容器中添加一个新元素,它的键即为该下标值。map的下标运算和vector下标运算相同:返回键相关联的值。运用map容器的这些特点,可以使编程编的很简练。如下面记录每个单词出现次数的例子:

  1. map<string,int> word_count;
  2. string word;
  3. //统计word_count中某个单词出现的次数
  4. while(cin>>word)
  5. ++word_count;

  map容器的insert使用的是pair类型的参数。如下表为map容器提供的insert操作。

  

  1. m.insert(e) e是一个用在m上的vaule_type类型的值。如果键e.first不在m中,则插入一个键为e.first值为e.seconde的元素。如果该键在m中已存在。则m保持不变。
  2. 该函数返回一个pair类型的对象,包含指向键为e.first的元素的map迭代器,以及一个bool类型的对象,表示是否插入成功。
  3. m.insert(beg,end) begend是标记元素范围的迭代器,其中的元素必须为m.value_type类型的键-值对。
  4. 对于该范围内的素有元素,如果它的键在m中不存在,则将该键及其关联的值插入m。返回void
  5. m.insert(iter,e) e是一个用在vaule_type类型的值。如果键不在m中,则创建新元素,并以迭代器iter为起点搜索新元素存储的位置。
  6. 返回一个迭代器,指向m中具有给定键的元素。

  如下:

  1. //方法一
  2. word_count.insert(map<string,int>::value_type("Anna",1));
  3.  
  4. //方法二,使用make_pair
  5. word_count.inser(make_pair("Anna",1));
  6.  
  7. //方法三,使用typedef
  8. typedef map<string,int>::value_type valType;
  9. word_count.insert(valType("Anna",1));

4.map中元素的查找与读取

  map中下标读取元素的缺点是当不存在该元素时会自动添加,有时这是我们不希望看到的。所以map提供了另外两个操作:count和find,用于检查某个键是否存在而不会插入该键。

  1. m.count(k) 返回mk出现次数
  2. m.find(k) 如果m容器中存在按k索引的元素,则返回指向该元素的迭代器。如果不存在,则返回超出末端迭代器

  count成员的返回值只能是0或1,因为map值允许一个键对应一个实例。如果返回值为非0,则可以用下标操作来获取该键所关联的值。

  1. int occurs=0;
  2. if(word_count.count("foobar"))
  3. occurs=word_count["foobar"];

  find操作凡湖指向元素的迭代器,如果元素不存在,则返回end迭代器。

  1. int occurs=0;
  2. map<string,int>::iterator it=word_count.find("foobar");
  3. if(it!=word_count.end())
  4. occurs=it->second;

5.map中删除元素

  从map容器中删除元素用erase操作,它有三种变化形式,如下:

  1. m.erase(k) 删除m中键为k的元素。返回size_type类型的值,表示删除的元素个数
  2. m.srase(p) m中删除迭代器p指向的元素。p必须指向m中确实存在的元素,而且不能等于m.end()。返回void
  3. m.erase(b,e) m中删除一段范围内的元素,该范围由迭代器对be标记。be必须标记m中的一段有效范围:即be都必须指向m中的元素或最后元素的下一个位置
  4. 而且,b要么在e的钱main,要么和e相等。返回void

6.map对象的迭代遍历

  map和其他容器一样也提供begin和end运算。

  1. map<string,int>::const_iterator map_it=word_count.begin();
  2.  
  3. while(map_it!=word_count.end()){
  4. cout<<map_it->first<<"occurs"
  5. <<map_it->second<<"time"<<endl;
  6. ++map_it;
  7. }

四、set类型

  set只是单纯的键的集合。当只想知道一个值是否存在时,使用set容器是最合适的。set容器支持大多数map的操作,包括构造函数、insert、count、find、erase操作。但是不包括下标操作,没有定义mapped_type类型。在set容器中value_type不是pair类型,而是与key_type相同的类型。与map一样,set容器中存储的键也是唯一的。

1.set的定义与使用

  使用set之前必须包含set头文件,set支持的操作基本与map提供的相同。

  1. vector<int > ivec;
  2. for(vector<int>::size_type i=0;i!=10;++i){
  3. ivec.push_back(i);
  4. ivec.push_back(i);
  5. }
  6.  
  7. //用ivec初始化set
  8. set<int> iset(ivec.begin(),ivec.end());
  9. cout<<ivec.size()<<endl; //输出20
  10. cout<<iset.size()<<end; //输出10

2.在set中添加元素 

  1. //方法一,直接插入
  2. set<string> set1;
  3. set1.insert("the");
  4.  
  5. //方法二,使用迭代器
  6. set<string> set2;
  7. set2.insert(ivec.begin(),ivec.end());

3.从set中获取元素

  set没有下标操作,为了通过键从set中获取元素,可使用find运算。如果仅是判断某个元素是否存在,也可使用count操作,返回值只能是1或0。

五、无序容器

无序容器是通过哈希函数来构建的,通过哈希函数映射到桶,无序容器的质量取决于哈希函数的质量和桶的质量与数量

桶接口

c.bucket_count()          //正在使用的桶的数量

c.max_bucket_count()  //最多能容纳多少个桶

c.bucket_size()             //第n个桶中有多少个元素

c.bucket(k)                    //k在那个桶

桶迭代

local-iterator                    //  可用来访问桶中元素的迭代器类型

const_local_iterator        // const版本

c.begin(n)    c.end(n)      //桶n的首尾元素迭代器

c.cbegin(n) c.cend(n)      //

哈希策略

c.load_factor()              //每个桶的平均元素数量,返回float

c.max_load_factor()      //维护桶

c.rehash()                      //重新哈希

c.reserve()                     //

c++11の关联容器的更多相关文章

  1. C++ Primer 5th 第11章 关联容器

    练习11.1:描述map 和 vector 的不同. map是关联容器,vector是顺序容器,关联容器与值无关,vector则与值密切相关 练习11.2:分别给出最适合使用 list.vector. ...

  2. [C++ Primer] : 第11章: 关联容器

    目录 使用关联容器 关联容器概述 关联容器操作 无序容器 使用关联容器 关联容器与顺序容器有着根本的不同: 关联容器中的元素是按关键字来保存和访问的, 按顺序容器中的元素是按它们在容器中的位置来顺序保 ...

  3. 【c++ Prime 学习笔记】第11章 关联容器

    关联容器的元素按照关键字来保存和访问,而顺序容器的元素是按照在容器中的位置来保存和访问 关联容器支持高效的关键字查找和访问 2种关联容器: map中的元素是关键字-值对(key-value对),关键字 ...

  4. 【C++ Primer 第11章】2. 关联容器操作

    练习答案 一.访问元素 关联容器额外类型别名  key_type 此容器类型的关键字类型 mapped_type 每个关键字关联的类型,只 适用于map mapped_type 对于set,与key_ ...

  5. 《C++ Primer》笔记 第11章 关联容器

    关联容器类型 解释 按关键字有序保存元素 -- map 关联数组:保存关键字-值对 set 关键字即值,即只保存关键字的容器 multimap 关键字可重复出现的map multiset 关键字可重复 ...

  6. 使用multimap创建重复键关联容器

    在“使用 <map> 库创建关联容器”一文中,我们讨论了标准库中的 map 关联容器.但那只是 map 容器的一部分.标准库还定义了一个 multimap 容器,它与 map 类似,所不同 ...

  7. ###STL学习--关联容器

    点击查看Evernote原文. #@author: gr #@date: 2014-08-23 #@email: forgerui@gmail.com STL中的关联容器. ###stl学习 |--迭 ...

  8. STL之关联容器---set, mutilset, map, mutilmap

    STL的容器分为序列容器和关联容器.它们所表达的数据结构各有不同: 序列容器:vector(变长数组), list(链表), queue(队列), heap(堆算法)等 关联容器:set/mutils ...

  9. C++ Primer 笔记——关联容器

    1.关联容器支持高效的关键字查找和访问,标准库提供8个关联容器. 2.如果一个类型定义了“行为正常”的 < 运算符,则它可以用作关键字类型. 3.为了使用自己定义的类型,在定义multiset时 ...

随机推荐

  1. 华为云.NET Core支持情况调查

    各大公有云都提供了开发者开发的SDK,今天我们来看看华为云对.NET Core的支持情况怎么样? .NET SDK地址 https://developer.huaweicloud.com/sdk#.N ...

  2. r.js合并实践

    项目中用到require.js做生产时模块开发,但上线要合并压缩,幸好它配套有r.js.下面就其用法说明一下. 首先建一个目录,里面的结构如下: require.js可以到r.js项目下载 r.js可 ...

  3. SDL 开发实战(七): SDL 多线程与锁机制

    为什么要用多线程?在音视频领域主要是实现音视频同步.实现了音视频同步,我们的播放器就基本上合格了. 这里我们将讲解一下SDL的多线程与锁机制. 多线程的好处主要是能使程序更加充分利用硬件(主要是CPU ...

  4. 爬虫须知的HTTP协议

    HTTP请求: 1.HTTP请求主要分为"Get"和"Post"两种方法. 2.当我们在浏览器输入URL http://www.baidu.com 的时候, 浏 ...

  5. RecyclerView实现一个页面有多种item,每个item有多个view,并且可以让任意item的任意view自定义监听,通过接口方法进行触发操作

    百度了很多贴子,看着大佬的博客,模仿尝试,最终都是以失败告终,api可能版本不一样, 毕竟博客大佬都是7~8前写的,日期新点的都是好几年前了,多次尝试,还是报出莫名其妙的错. 哎,忧伤. 翻阅各种资料 ...

  6. python接口自动化(十)--post请求四种传送正文方式(详解)

    简介 post请求我在python接口自动化(八)--发送post请求的接口(详解)已经讲过一部分了,主要是发送一些较长的数据,还有就是数据比较安全等.我们要知道post请求四种传送正文方式首先需要先 ...

  7. Node.js 命令行工具的编写

    日常开发中,编写 Node.js 命令行工具来完成一些小任务是很常见的操作.其编写也不难,和日常编写 Node.js 代码并无二致. package.json 中的 bin 字段 一个 npm 模块, ...

  8. 目录导航「深入浅出ASP.NET Core系列」

    希望给你3-5分钟的碎片化学习,可能是坐地铁.等公交,积少成多,水滴石穿,谢谢关注. 入门篇 引子 1.1专题介绍 1.2环境安装 1.3创建项目 1.4部署到IIS 1.5准备CentOS和Ngin ...

  9. Apache web服务器(LAMP架构)(week3_day4)--技术流ken

    apache介绍 1).世界上使用率最高的网站服务器,最高时可达70%:官方网站:apache.org 2).http 超文本协议 HTML 超文本标记语言 3).URL 统一资源定位符 http:/ ...

  10. sql 脚本编写之路 常用语句(一) 1.用一个表中的某一列更新另外一个表的某些列:

    for ACCESS 数据库: update a, b set a.name=b.name1 where a.id=b.id for SQL Server 数据库: update a set a.na ...