某些STL中用的甚至是双向循环链表。既然是基于双向链表显然其不是连续存储的。
所以每个节点不光包括val 值,还有前后两个指针。
list包含了一个指针,重载了运算符,实现迭代器的递增递减与取值操作
list实际上是一个带有头节点的双向循环链表,node指针指向空的头节点
由此begin就是node->next的val
end 就是node本身,因为是循环的
empty判断node->next==node?即可
back就重载–,找到node的上一个节点。
注接下文array:
不确定大小/频繁插入删除用list
大量查找,用array
这样符合我们操作系统里的局部性原理。
用法:
array<种类,数目> name {具体数值初始化};
因为array容器中新增了类似at()这样的成员函数,其会检查n是否有效,否则抛出异常,所以比普通数组安全。
动态数组,用于 O(1) 的随机读取.
实现原理:
由三个指针实现,
第一个指针指向vector起始位置
第二个指针指向目前有数据的末尾
第三个指针指向整个vector容器所占内存的末尾。
由此实现:
template<class _Ty,
class _Ax>
class vector
: public _Vector_val<_Ty, _Ax>
{ // varying size array of values
public:
/********/
protected:
pointer _Myfirst; // pointer to beginning of array
pointer _Mylast; // pointer to current end of sequence
pointer _Myend; // pointer to end of array
};
由此:
注意:
end 指向第二个指针
size 是2-1 而capacity 是3-1
注意resize的时候,是新在堆中开辟内存,赋值之后删除旧数组
template <class _Ty, class _Alloc = allocator<_Ty>>
class vector{
public:
iterator begin() {return _Myfirst;}
iterator end() {return _Mylast;}
size_type size() const {return size_type(end() - begin());}
size_type capacity() const {return size_type(_Myend - begin());}
bool empty() const {return begin() == end();}
reference operator[] (size_type n) {return *(begin() + n);}
reference front() { return *begin();}
reference back() {return *(end()-1);}
...
};
详细使用见:
添加链接描述
支持O(1)的随机读取和头部、尾部的频繁增删
为了管理这些连续空间,deque 容器用数组(数组名假设为 map)存储着各个连续空间的首地址。也就是说,map 数组中存储的都是指针,指向那些真正用来存储数据的各个连续空间。
当 deque 容器需要在头部或尾部增加存储空间时,它会申请一段新的连续空间,同时在 map 数组的开头或结尾添加指向该空间的指针,由此该空间就串接到了 deque 容器的头部或尾部。
遍历的时候四个指针,一个头first一个尾last,一个cur,最后一个node指向map数组指针,如果cur遍历到边缘,就用node指针来更新前三个指针。
由这四个指针,维护两个迭代器:一个start记录map数组中首个连续空间的信息,一个finish迭代器记录map数组最后一个连续空间的信息。但是start的cur指向连续空间的第一个数,而finish的cur指向连续空间的最后一个数。
默认基于deque实现,后入先出LIFO。
常用于深度优先搜索,字符串匹配等问题。
首先要了解内存分区:
区别:
默认基于deque,先入先出FIFO
常用于广度优先搜索。
最大值先出的数据结构,默认基于vector实现堆结构。它可以在O(nlogn)的时间排序数组,O(logn) 的时间插入任意值,O(1) 的时间获得最大值,O(logn) 的时间删除最大值。priority_queue 常用于维护数据结构并快速获取最大或最小值。
默认基于红黑树(一种特殊的二叉查找树)。元素不可重复。
它可以在 O(nlogn) 的时间排序数组,O(logn) 的时间插入、删除、查找任意值,O(logn) 的时间获得最小或最大值。这里注意,set 和 priority_queue 都可以用于维护数据结构并快速获取最大最小值,但是它们的时间复杂度和功能略有区别,如priority_queue默认不支持删除任意值,而set获得最大或最小值的时间复杂度略高,具体使用哪个根据需求而定。
在set的基础上加上映射关系,使得每个key存一个value值。
可以在 O(1) 的时间快速插入、查找、删除元素,常用于快速的查询一个元素是否在这个容器内。
如果需要每次判断一个元素在不在一个vector内,我们可以将其转化成一个哈希集:这样就能很快的查找:
unordered_set<int> dict(v.begin(),v.end());
if(v.count(a))
{
...
}
在 unordered_set 的基础上加上映射关系,可以对每一个元素 key 存一个值 value。在某些情况下,如果 key 的范围已知且较小,我们也可以用 vector 代替 unordered_map,用位置表示 key,用每个位置的值表示 value
详情见:
添加链接描述