是一个封装了动态大小数组的顺序容器;数组内容器严格按照线性顺序排序,支持随机访问,因此提供随机访问指针,例如vector::iterator ivite; 并且为了降低空间配置得速度成本,vector实际分配大小要比需求大一点。size()表示目前实际存储的大小,capacity()表示分配的空间大小,是要大于size的,start表示起始地址,finish表示最后一个数据地址,end_of_storage表示分配的最后地址。
扩容: 如果容量不足,容量会扩充至二倍,如果依旧不足,那就直接扩充到足够大的容量。
构造函数
:
增加元素:
删除函数:
遍历函数:
其他函数:
bool empty() const:判断向量是否为空,若为空,则向量中无元素
int size() const:返回向量中元素的个数
void swap(vector&):交换两个同类型向量的数据
void insert():指定位置插入元素,多种重载版本
对于insert函数,插入点后元素个数和要插入的元素个数不同,插入的算法也不相同,很神奇,研究了半天为什么这么做,其实主要就是考虑到finish后面的未初始化内存不能被copybackward函数操作,因此只能使用uninitialized_copy函数先处理这部分,先覆盖掉已经分配但未初始化的内存,但这个复制操作需要消耗性能,因此要尽可能少用。因此对于插入点后元素大于新增元素时,所以只能最后n个数据复制到finish位置后面去,虽然消耗性能,但没办法,剩下一点(前面的数据),就利用copybackward函数移动就好,最后再把新数据插入到指定位置;
但对于插入点后元素数量小于新增元素个数,说明要把最后的元素都移动到finish后面的未初始化内存中去,copybackward函数就办不到了,只能利用uninitialized_copy复制到最后去,在给指定位置填充新增元素,但要注意,uninitialized_fill_n函数性能比fill函数好,但前者只能处理未初始化内存,因此先用uninitialized_fill_n函数填充finsh后的多余未初始化内存区域(图中第一步),最后对于需要覆盖的内存(最后一步),再用fill,充分考虑性能问题。
其中
是一个非常重要的容器类,用于存储元素集合,支持双向迭代器。
是 C++ 标准模板库(STL)中的一个序列容器,它允许在容器的任意位置快速插入和删除元素。与数组或向量(
)不同,
不需要在创建时指定大小,并且可以在任何位置添加或删除元素,而不需要重新分配内存。可以理解为一个双向链表,分散存储在内存空间里,而不是必须存储在一整块连续的内存空间中。list基于双向链表的结构, 他所以可以在序列已知的任何位置快速插入或删除元素(时间复杂度为O(1)
)。并且在 list 容器中移动元素,也比其它容器的效率高。但是不支持随机访问。因此list提供的是双向迭代器。
相比于vector,list迭代器不会因为insert而失效,只会在erase操作时,对应的一个迭代器会失效。而vector存在严重的迭代器失效场景
迭代器:
begin() 返回指向容器中第一个元素的双向迭代器。
end() 返回指向容器中最后一个元素所在位置的下一个位置的双向迭代器。
rbegin() 返回指向最后一个元素的反向双向迭代器。
rend() 返回指向第一个元素所在位置前一个位置的反向双向迭代器。
cbegin() 和 begin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
cend() 和 end() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crbegin() 和 rbegin() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
crend() 和 rend() 功能相同,只不过在其基础上,增加了 const 属性,不能用于修改元素。
empty() 判断容器中是否有元素,若无元素,则返回 true;反之,返回 false。
size() 返回当前容器实际包含的元素个数。
max_size() 返回容器所能包含元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。
访问:
是标准模板库(STL)的一部分,它提供了双端队列(double-ended queue)的实现。双端队列是一种允许在两端进行插入和删除操作的线性数据结构。它提供了快速的随机访问能力,同时允许在两端进行高效的插入和删除操作。这使得
成为处理需要频繁插入和删除元素的场景的理想选择。
与vector区别:vector虽然技术上也提供了两端数据的插入和删除,但本质是单向的连续线性空间,头部操作需要移动所有元素,效率太低‘deque允许常数时间内对端头元素增删;deque没有容量,是动态的以分段连续空间组合而成。随时可以增加一段新的空间链接起来。
虽然提供随即迭代器,但效率远不如vector,因此数组操作尽可能使用vector。并且在deque中进行sort,会先把数据拷贝在vector中,进行sort,然后在放回deque中,效率底下,因此deque只适合于在两端增删的场景——stack和queue
deque() |
默认构造函数,创建一个空的 deque 容器。 |
---|---|
deque(size_type n) |
创建一个包含 n 个默认值元素的 deque 容器。 |
deque(size_type n, const T& value) |
创建一个包含 n 个值为 value 的 deque 容器。 |
deque(initializer_list |
使用初始化列表 il 构造 deque 容器。 |
operator= |
赋值操作符,赋值给 deque 容器。 |
assign() |
用新值替换 deque 容器中的所有元素。 |
at(size_type pos) |
返回 pos 位置的元素,并进行范围检查。 |
operator[](size_type pos) |
返回 pos 位置的元素,不进行范围检查。 |
front() |
返回第一个元素的引用。 |
back() |
返回最后一个元素的引用。 |
begin() |
返回指向第一个元素的迭代器。 |
end() |
返回指向末尾元素后一位置的迭代器。 |
rbegin() |
返回指向最后一个元素的逆向迭代器。 |
rend() |
返回指向第一个元素之前位置的逆向迭代器。 |
empty() |
检查容器是否为空。 |
size() |
返回容器中的元素个数。 |
max_size() |
返回容器可容纳的最大元素个数。 |
clear() |
清除容器中的所有元素。 |
insert(iterator pos, const T& value) |
在 pos 位置插入 value 元素。 |
erase(iterator pos) |
移除 pos 位置的元素。 |
push_back(const T& value) |
在容器末尾添加 value 元素。 |
pop_back() |
移除容器末尾的元素。 |
push_front(const T& value) |
在容器前端添加 value 元素。 |
pop_front() |
移除容器前端的元素。 |
resize(size_type count) |
调整容器大小为 count ,多出部分用默认值填充。 |
swap(deque& other) |
交换两个 deque 容器的内容。 |
get_allocator() |
返回一个用于构造双端队列的分配器对象的副本。 |
stack: 栈,先进后出,一端进出,不允许遍历,这种改变容器接口,得到另一种结构的称为配接器
==queue:==队列,先进先出,一端只进,另一端只出,
关联容器,它存储了一组唯一的元素,并按照一定的顺序进行排序。
提供了高效的元素查找、插入和删除操作。它是基于红黑树实现的,因此具有对数时间复杂度的查找、插入和删除性能。有序、不能重复。同时迭代器失效只存在于被删除元素。
insert(元素)
: 插入一个元素。erase(元素)
: 删除一个元素。find(元素)
: 查找一个元素。size()
: 返回容器中元素的数量。empty()
: 检查容器是否为空。提供了一种基于哈希表的容器,用于存储唯一的元素集合。与 set
不同,unordered_set
不保证元素的排序,但通常提供更快的查找、插入和删除操作。
无序、不能重复、有哈希函数
insert(元素)
: 插入一个元素。erase(元素)
: 删除一个元素。find(元素)
: 查找一个元素。size()
: 返回容器中元素的数量。empty()
: 检查容器是否为空。 是标准模板库(STL)的一部分,它提供了一种关联容器,用于存储键值对(key-value pairs)。
map
容器中的元素是按照键的顺序自动排序的,这使得它非常适合需要快速查找和有序数据的场景。有序、键值对、唯一、双向迭代。底层红黑树
提供了一种基于哈希表的键值对容器。与 std::map
不同,unordered_map
不保证元素的排序,但通常提供更快的查找速度。
无序、键值对、唯一
优先队列,缺省由高到低,由maxheap实现,底层是一个vector的完全二叉树。同样是一种适配器;
push:先利用push_back放入底层vector中,在利用push_heap重新排序,实现优先队列的插入
pop:先利用pop_heap,把最大(最小)元素放到vector尾部,再利用pop_back弹出。
优先队列只有顶部top元素能被访问,因此不提供迭代器
单向链表,对应迭代器是单向的,虽然功能不如list,但slist内存小,某些操作更快,特定需求下比list性能好。
单向链表特点决定,某个节点插入数据,只能插入该节点之后,这与STL其他容器操作相反(例如list,某个点插入新数据,新数据是在原始节点之前的,vector也是),因此提供insert_after,erase_after。同时,链表尾部(back)增删数据显然效率低下,因此slist只提供push_front,pop_front。也就是虚拟头节点后增删数据,因此如果给一个slist插入数据1,2,3,4。实际单链表数据是相反的4,3,2,1有没有栈的味道?
其他容器操作相反(例如list,某个点插入新数据,新数据是在原始节点之前的,vector也是),因此提供insert_after,erase_after。同时,链表尾部(back)增删数据显然效率低下,因此slist只提供push_front,pop_front。也就是虚拟头节点后增删数据,因此如果给一个slist插入数据1,2,3,4。实际单链表数据是相反的4,3,2,1有没有栈的味道?