【c++容器】顺序容器和关联式容器
一、顺序容器
| vector | 可变大小数组。支持快速随机访问。在尾部之外的位置插入或者删除元素很慢 |
| deque | 双端队列。支持快速随机访问,在头尾位置插入/删除元素很快 |
| list | 双向链表。只支持双向顺序访问。在list中任何位置进行插入/删除速度都很快 |
| forward_list | 单向链表。只支持单向顺序访问。在链表的任何位置进行插入/删除都很快 |
| array | 固定数组大小。支持快速随机访问,不能添加或删除元素 |
| string | 与vecotr相似的容器,但专门用于保存字符。随机访问快。在尾部插入/删除速度快 |
1、vector
具体见:【c++容器】之vector 和 【c++容器】之vector(2)
string 和 vector 将元素保存在连续的内存空间中,由于元素是连续存储的,由元素的下标来计算其地址是非常快速的。但是,在这两种容器的中间位置添加或删除元素就会非常耗时:在一次插入或删除操作后,需要移动插入/删除位置之后的所有元素,来保持连续存储。而且,添加一个元素有时可能还需要分配额外的存储空间。在这种情况下,每个元素都必须移动到新的存储空间中。
2、duque
具体见:【c++容器】之deque
deque是一个更为复杂的数据结构。与string和vector类似,deque支持快速的随机访问。与 string 和 vector 一样,在 deque 的中间位置添加或删除元素的代价(可能)很高。但是,在 deque 的两端添加或删除元素都是很快的,与 list 或forward_list 添加删除元素的速度相当。
3、list
具体见:【c++容器】之list
list 和 forward_list 两个容器的设计目的是令容器任何位置的添加和删除操作都很快速。作为代价,这两个容器不支持元素的随机访问:为了访问一个元素,我们只能遍历整个容器。而且,写 vector、deque 和array 相比,这两个容器的额外内存开销也很大。
4、forward_list
forward list 和array 是新 C++标准增加的类型。与内置数组相比,array 是一种更安全、更容易使用的数组类型。与内置数组类似,array 对象的大小是固定的。因此,array 不支持添加和删除元素以及改变容器大小的操作。forward_list 的设计目标是达到与最好的手写的单向链表数据结构相当的性能。因此,forward_list 没有 size操作,因为保存或计算其大小就会比手写链表多出额外的开销。对其他容器而言,size保证是一个快速的常量时间的操作。
5、array
6、string
二、关联容器
按关键字有序保存元素
| 按关键字有序保存元素 | |
| map | 关联数组:保存关键字-值对 |
| set | 关键字即值,即只保存关键字的容器 |
| multimap | 关键字可重复的map |
| multiset | 关键字可重复的set |
无序集合
| 无序集合 | |
| unordered_map | 用哈希函数组织的map |
| unordered_set | 用哈希函数组织的set |
| unordered_multimap | 哈希组织的map,关键字可以重复出现 |
| unordered_multiset | 哈希组织的set,关键字可以重复出现 |
1、map和multimap
map关键字-值对的集合。例如,可以将一个人的名字作为关键字,将其电话号码作为值。我们称这样的数据结构为“将名字映射到电话号码”。map 类型通常被称为关联数组(associative array)。关联数组与“正常”数组类似,不同之处在于其下标不必是整数。我们通过一个关键字而不是位置来查找此值。给定一个名字到电话号码的map,我们可以使用一个人名字作为下标来获取此人的电话号码。
2、set和multiset
set 就是关键字的简单集合。当只是想知道一个值是否在在时,set是最有用的。例如,一个企业可以定义一个名为 bad_checks 的 set 来保存那些曾经开过空否在其中。头支票的人的名字。在接受一张支票之前,可以查询 bad_checks 来检查顾客的名字是否在其中。
3、unordered_map
具体见:【c++容器】map和unordered_map的差别和使用
4、unordered_set
| 集合 | 底层实现 | 是否有序 | 数值是否可以重复 | 能否更改数值 | 查询效率 | 增删效率 |
|---|---|---|---|---|---|---|
| std::set | 红黑树 | 有序 | 否 | 否 | O(logn) | O(logn) |
| std::multiset | 红黑树 | 有序 | 是 | 否 | O(logn) | O(logn) |
| std::unordered_set | 哈希表 | 无序 | 否 | 否 | O(1) | O(1) |
std::unordered_set底层实现为哈希表;
std::set 和std::multiset 的底层实现是红黑树,红黑树是一种平衡二叉搜索树,所以key值是有序的,但key不可以修改,改动key值会导致整棵树的错乱,所以只能删除和增加。
| 映射 | 底层实现 | 是否有序 | 数值是否可以重复 | 能否更改数值 | 查询效率 | 增删效率 |
|---|---|---|---|---|---|---|
| std::map | 红黑树 | key有序 | key不可重复 | key不可修改 | O(logn) | O(logn) |
| std::multimap | 红黑树 | key有序 | key可重复 | key不可修改 | O(logn) | O(logn) |
| std::unordered_map | 哈希表 | key无序 | key不可重复 | key不可修改 | O(1) | O(1) |
std::unordered_map 底层实现为哈希表;
std::map 和std::multimap 的底层实现是红黑树。同理,std::map 和std::multimap 的key也是有序的。
当我们要使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。
那么再来看一下map ,在map 是一个key value 的数据结构,map中,对key是有限制,对value没有限制的,因为key的存储方式使用红黑树实现的。
更多推荐
所有评论(0)