- 关联容器和顺序容器的不同点
- 关联容器是基于关键字的。关键字决定了值存储的位置,也决定了访问的时候到哪里去找到。关键字起到的是索引的作用。似乎是废话。
- 关联容器包括有
- 按照关键字有序保存 set,map,multiset, multimap,
- 无序集合,通过哈希表来实现 unordered_map, unordered_set, unnordered_multiset, unordered_multimap. - set和map的作用:
- set的值只有一个关键字,常常用来知道一个元素是否在set中存在。是const的
- map的value_type 是一个pair,也就是一个键值对。pair有两个元素,一个first,一个second。first是const的。map常常用来统计。
- set和map的初始化
- 可以使用** {} **来赋初值。也可以使用构造函数,比如在括号里是另外一个set或者map,或者使用另外一个容器的begin和end指针,来进行初始化。
- set和map的关键字要求
- set和map是关联容器,是基于关键字的。对于关键字也是有要求的,不是随意定义一种数据类型就可以作为关键字。
- 有序容器,也就是不带unordered的数据类型,是需要关键字可以使用
<
来定义大小关系的。 - 对于有序容器的这种要求,我们采用一个函数类型(用来完成比较任务)来满足这种需求。就是在定义map/set的时候,在<>中元素后面传入另外一个类型:自定义操作类型。可以使用
decltype(函数名)*
来指明。
- pair类型
- pair类型是map的value_type, 其也是一个模板类。为标准库的一部分,在< unility > 文件中
- pair包括两个公开成员变量。一个是first,一个是second。
- pair对象的初始化操作,使用
- pair<T1, T2> p(v1, v2)
- 使用初始化器
- 使用make_pair
- pair的公开成员变量可以直接访问。
- pair定义了关系运算符。 == != >= 等
- 再pair作为返回值返回的时候,可以使用 { v1, v2 }。也就是使用初始化列表来构建一个匿名的pair,返回。再早期的c++里面不允许这样做。也可以使用make_pair()来进行返回。
- 关联容器的基本操作
-
关联容器数据类型有key_type, mapped_type, value_type三种,可以使用作用域运算符来进行提取。
-
关联容器的迭代器也是这个类型空间的,名字叫做 iterator。迭代器有const iterator(相当于常量指针)和iterator。但是由于set和map的关键字都是const的,实际上都不可以更改。但是iterator可以更改pair的second值。但是const iterator不可以更改。两者都可以更改指针本身的值。也就是可以通过 ++ 完成遍历操作。
-
关联容器可以适用于哪些算法
泛型算法不适用。其不适用于需要修改,重排元素的值的算法。因为元素中有const修饰。搜索算法似乎也效率不高,如果需要的话,可以将值腾出来。 -
添加一个元素
- set添加
我们使用insert添加元素。有两个版本的insert,可以是一对迭代器,也可以是一个初始化列表。也就是说,可以一次插入多个值。 - map添加
每次insert,参数必须是一个pair,不可以是多个pair。pair的临时制作前面说过,可以使用 {} ,也可以使用make_pair,或者使用初始化方法。返回值为一个pair。first为插入的指针,也就是迭代器。second为是否成功插入。再map中,当关键字已经存在,会失败,没有任何影响。再multimap中,总会成功。
- set添加
-
删除一个元素
使用erase函数。这个函数有三个版本。1 参数为一个迭代器,表示删除指定元素,返回值为void。 2 参数为一个迭代器对,表示删除指定区间的元素,返回值为void (这两个很像顺序容器) 3 参数为一个key_type 类型的值,表示删除key_type为指定的元素。返回删除的个数。对于非multi 为0或者1.对于multi,>=0 -
map下标操作
map支持下标操作,还有at函数,里面内容都是关键字内容。at()当对应元素不存在,会抛出异常。而下标操作如果没有的话,会创建一个,并进行初始化。这和顺序容器的下标操作大不相同。因此想要知道一个元素是否再map中,千万不要用下标操作。
map的下标操作返回值为一个mapped_tyoe类型的值。并且是一个左值,可以进行写操作。 -
查找元素信息
由于map的下标操作不可以用来仅仅测试一个元素是否存在。我们使用count操作或者find操作来仅仅检查是否存在。count()用来数一数有多少个符合元素,返回int 出现的次数。如果为0,说明未出现。find()用来返回一个指向这个元素的迭代器。没有的话,返回.end()迭代器。
可以使用lower_bound() 和 upper_bound() 来返回一个迭代器范围,打印出在multi中的所有我们需要查找的元素,如果不存在就指向相同的指针,则不打印。 -
无序容器
特点就是: 使用哈希函数和关键字类型的 == 运算符来确定元素的位置。适用于关键字类型本身就是无序的情况 或者 使用有序容器发现性能比较低的情况下。
无序容器的原理就是 一组桶 。通过哈希函数将元素映射到相应的桶里面。允许一个桶里面有多个元素。
由于标准库里面已经对基本数据类型和其他的常用类进行了hash的适配。可以直接使用。但是对于自定义的类型,想要作为关键字,必须要有相当于 == 和 hash运算的部分。我们采用函数来实现。由于其他类型的hash运算是通过hash< type >来实现的,我们可以使用一个函数来利用这个hash来实现我们自己的hash。至于比较操作就也是实现一个函数即可。
-