容器分为:
序列式容器:array,vector(用算法呈现heap(由heap实现priority-queue)),list,deque(配接器(stack,queue))
关联式容器:RB-tree(set,map,multiset,multimap),hashtable(hash_set,hash_map,hash_multiset,hash_multimap)
内含关系:heap内含一个vector,stack和queue内含一个deque,set/map/multiset/multimap内含RB_tree。
vector:
数据安排和操作方式,与array相似,唯一差别在于空间运用的灵活性。
array是静态空间,一旦配置了就不能改变(若空间不足:1.申请空间,2.copy,3.free之前空间)
vector是动态空间
vector迭代器:
vector维护的是一个连续线性空间,不管元素型别,普通指针都可以作为vector迭代器(vector迭代器就是普通指针)
template<class T,class Alloc=alloc>
class vector{
public:
typedef T value_type;
typedef value_type* iterator;
};
vector<int>::iterator iiter等价于int * iiter;
vector数据结构
线性连续空间
template<class T,class Alloc=alloc>
class vector{
protected:
iterator start;//目前使用空间的头
iterator end;//目前使用空间的尾
iterator end_of_storage;//目前可用空间的尾
};
vector的成员函数:size()和capacity()区别在于:
size()返回的是finish-start(里面的元素个数),而capacity()返回的是end_of_storage-start(目前占有的空间大小)
一旦size()==capacity(),下次新增元素就会扩充至容量的两倍,过程如下:
1.确定申请大小,2.分配空间,3.copy元素,4.destroy并释放原空间到free-list,5.更新偏移
注:一旦空间重新配置,指向原vector的迭代器就都失效了,因为指向的原空间已经不存在
list
每次插入或者删除,就配置或释放一个元素空间
list有一个重要性质:插入不会造成原有的list迭代器失效(vector可能失效),删除操作只有指向被删除元素的迭代器失效。
list节点结构:
template <class T>
struct __list_node{
typedef void* void_pointer;
void_pointer prev;
void_pointer next;
T data;
};
list迭代器:
template<class T,class Ref,class Ptr>
struct __list_iterator{
typedef __list_iterator<T,&T,*T> literator;
typedef __list_node<T>* link_node;
link_type node; //指向node的节点,为了迭代器遍历(一开始指向尾端的空白节点)
};
list的数据结构:
SGI list是一个环状双向链表,只需一个指针,就能遍历整个链表
deque
deque是双向开口的连续线性空间,vector是单向开口的连续线性空间
vector和deque对比:
1.deque允许常数时间内对头端进行元素的插入或移除
2.deque没有capacity概念,它的结构是分段连续空间组合而成,随时增加一段新的空间并链接起来,
由于第二点,deque的迭代器不是普通指针,复杂度很高,所以非必要的话,尽量使用vector,
如果需要对deque进行排序,为了最高效率,1.deque先复制到vector中,2.vector排序(STL的sort算法)3.复制回deque
deque中控器:
deque是逻辑上的连续空间,由一段一段的定量连续空间构成,
deque最大任务就是维护其整体连续的假象,避开了vector“重新配置,复制,释放”的轮回,代价是复杂的迭代器架构
deque采用一块所谓的map作为主控(map是一小块连续空间,每个map节点指向一块较大的连续线性空间,缓冲区(deque存储主体))
默认