【读书笔记】序列式容器
所谓序列式容器,其中的元素都可序的,但未必是有序。
vector,与array非常相似,唯一的区别是array是静态空间,一旦配置了就不能改变;vector是动态空间,随着元素的加入,它的内部机制会自行扩充空间以容纳新元素。
普通指针可以作为vector的迭代器。
为了降低空间配置时的速度成本,vector实际配置的大小可能会比客户端需求量更大一些,以备将来可能的扩充,可通过capacity方法获取容量大小。
vector的所谓动态增加大小,并不是在原空间之后接续新空间(因为无法保证原空间之后尚有可供配置的空间),而是以原大小的两倍另外配置一块较大的空间,然后将原来的内容拷贝过来,然后才开始在原内容之后构造新元素,并释放原空间。因此,对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了。
list,普通指针不能作为list的迭代器,因为其节点不能保证在存储空间中连续存在。由于list是一个环状双向链表,迭代器必须具备前移后移能力。
list的插入操作(insert)和接合操作(splice)都不会造成原有的迭代器失效。删除操作也只是指向被删除元素的迭代器失效,其他迭代器不受影响。
STL中的插入都是指在某节点之前插入。
erase和remove的区别:erase通过迭代器删除,remove通过值删除。
deque
vector是单向开口的连续线性空间,deque则是一种双向开口的连续线性空间。即可以在头尾两端分别做元素的插入和删除操作。
deque和vector的区别:一是deque允许于常数时间内对头端进行元素的插入或移除操作,二是在于deque没有所谓容量观念,因为它是动态的以分段连续空间组成的,随时可以增加一段新的空间并连接起来。
deque效率比较差,尽量使用vector。
deque是由一段一段的定量连续空间构成,一旦有必要在deque的前端或尾端增加新空间,便配置一段定量连续空间,串接在整个deque的头端或尾端。代价是复杂的迭代器架构。
deque采用一块所谓的map作为主控,这里的map是一小块连续空间,其中每个元素都是指针,指向另一段连续性空间,称为缓冲区。缓冲区才是deque的存储空间主体。如下图所示。
stack
stack是一种先进后出的数据结构。除了最顶端的元素外,没有任何方法可以存取stack的其他元素。
stack不提供走访功能,也不提供迭代器。
queue是一种先进先出的数据结构。除了最底端可以加入、最顶端可以取出外,没有任何方法可以存取queue的其他元素。
queue不提供遍历功能,也不提供迭代器。
heap分为大堆小堆两种,前者每个节点的键值都大于或等于其子节点的键值,后者每个节点的键值都小于或等于其子节点的键值。
pop_heap后,最大元素只是被置放在底部容器的最尾端,尚未被取走,如果要取其值,可以使用底部容器(vector)的back函数,如果要移走则可使用底部容器的pop_back函数。
heap所有元素都必须遵循特别的排列规则,所有heap不提供遍历功能,也不提供迭代器。
priority_queue是一个拥有权值观念的queue,其内的元素并不依照推入的次序排列,而是自动依照元素的权值排列,权值最高排列在最前面。一般底层是以max_heap完成。
slist是一个单链表。单链表所耗的空间更小,某些操作更快。在STL中插入操作会将新元素插入于指定位置之前。但作为单向链表,没有任何方便的方法可以回头定位出前一个位置。除了在slist起点处附近的区域之外,在其他位置采用insert和erease都是不明智之举。同理slist不提供push_back 只提供push_front,因此slist的元素次序会和元素插入的方向相反。