STL序列容器总结
STL 的各种容器:
一、vector
vector 的数据安排及操作方式,与 array 非常相似,两者的区别在于,array 是静态空间,一旦配置不能改变,vector 是动态空间。
1. vector 的数据结构
通过这个三个迭代器可计算得到容器内元素个数和容器当前容量。
2. vector 的空间分配与容量
增加新元素时,若超过容器当前的容量,则容量会扩充至两倍,若仍不足则扩张至足够大的容量。只要没有操作需要超出 vector 的容量,就不能重新分配内存空间。一旦引起空间重新配置,指向原 vector 的所有迭代器就都失效了。
扩张空间并不是简单地在原空间之后新增空间,而是一个“重新配置新空间、元素移动、释放原空间”的复杂过程。
size() 操作获取容器内元素的个数,capacity() 操作获取容器当前的最大容量,空 vector 的size和capacity都是0。可以通过 reserve(n) 操作分配至少n个元素的内存空间(可能更大),当需要容量小于当前容量时,容器不会退回内存空间。
对于 vector 的任何操作,只要引起空间重新配置,指向原 vector 的所有迭代器就都失效了。
3. vector 的元素操作
pop_back 即删除尾端元素;erase 可清除某个位置上的元素或某个区间内的元素;clear 即 erase(begin(), end())。
二、list
1. list 基本性质
- 相较于 vector 的连续线性空间,list 每次插入或删除一个元素,就配置或释放一个元素空间。
- STL中的 list 是一个双向链表,而且还是环状双向链表。
- list 任意元素的插入和移除操作都是常数时间。
- 插入操作和接合操作都不会造成 list 原有迭代器失效。
- 删除操作仅指向被删除元素的迭代器失效。
- STL 提供了一个单向链表(single linked list)slist。
2. list 的元素操作
list 内部提供一个迁移操作(transfer),将某连续范围的元素迁移到某个特定位置之前,技术上是节点间的指针移动。该操作为复杂操作如 splice、sort、merge 奠定基础。
- push_front / push_back,插入一个节点作为头节点 / 尾节点。
- pop_front / pop_back,移除头节点 / 尾节点。
- erase,移除迭代器所指结点。
- remove,移除数值为 value 的所有元素。
- unique,移除数值相同且连续的元素,重复元素剩一个。
- splice,将某个连续范围的元素从一个list移动到另一个(或同一个)list的某个位置。
- merge,合并两个 list,两个 lists 必须是经过递增排序的。
- reverse,将 list 的内容反转。
- sort,list 不能使用STL算法 sort,必须使用自己的成员函数 sort。
三、deque
1. 基本性质
- 相对于 vector 单向开口的连续线性空间,deque 则是一种双向开口的连续线性空间。即可在头尾两端分别做元素的插入和删除操作。
- 与 vector 的最大差异,一是 deque 允许常数时间内在头部进行元素的插入或移除操作;二是 deque 没有容量的概念,是动态地以分段连续空间组合而成,随时可以增加一段新的空间并连接起来。
2. deque 如何实现分段连续空间的中央控制。
deque 采用一块所谓的 map(非STL的map容器)作为主控,map 是一块连续空间,其中的每个元素都是指针,指向另一段连续线性空间,称为缓冲区,缓冲区才是真正的 deque 储存空间主体。当 map 使用率满载时,就需要再找一块更大的空间来作为 map。STL 允许指定缓冲区的大小,默认值0表示将使用512 bytes 缓冲区。
3. deque 的数据结构
除了要维护一个指向 map 的指针,还需要维护 start 和 finish 两个迭代器,分别指向第一缓冲区的第一个元素和最后缓冲区的最后一个元素(的下一位置),此外还需要记住 map 的大小 map_size。一旦 map 所提供的节点不足,就必须重新配置更大的一块 map。
四、stack
1. 基本性质
- stack 只有一个出口,是一种先进后出的数据结构。
- STL 中以 deque 为 stack 底部结构。具有这种“修改某物接口,形成另一种风貌”之性质者,称为 adapter 配接器。故 STL stack 往往不归为 container 容器,而归为 container adapter。
- stack 没有迭代器,不提供走访功能。
- 除了 deque 之外,以 list 为底层结构也可以形成一个 stack。
2. 元素操作
empty、size、top、push、pop。
五、queue
1. 基本性质
- queue 允许最底端可以加入、最顶端可以取出。
- STL 中以 deque 为底层结构,封闭其底端的出口和顶端的入口,形成 queue。
- queue 没有迭代器,不提供遍历功能。
- queue 同样可以以 list 为底部结构实现。
- STL queue 往往不归为 container 容器,而归为 container adapter。
六、heap
1. 基本性质
- heap 可分为 max_heap 和 min_heap,前者每个节点的键值都大于等于其子节点键值,后者每个节点的键值都小于等于其子节点键值。
- 以数组表述树的方式,称为隐式表述法。heap 需要动态改变大小,故以 vector 代替数组实现。
- STL 提供的是 max_heap。
2. heap 算法
(1)push_heap,新加入的元素首先放在最下一层作为叶节点,然后执行一个上溯程序,将新节点与其父节点比较,若键值比父节点大,就对换位置,一直上溯至不需要对换或到根节点为止。
(2)pop_heap,pop 操作取走根节点(其实是移至 vector 的最后一个元素位置)之后,原来该位置的元素填入根节点,然后将其与两个子节点进行比较,与较大子节点对换位置,如此一直下溯,直到该元素大于两个叶节点或下溯至叶节点为止。
(3)sort_heap,每次 pop_heap 可获得 heap 中键值最大元素,持续对整个 heap 做 pop_heap 操作,每次将操作范围从后向前缩减一个元素,最终便得到一个递增序列。排序过后,原来的 heap 已不再是合法的 heap 了。
(4)make_heap,将一段现有的数据转化为一个 heap。
七、priority_queue
1. 基本性质
- priority_queue,缺省(默认)情况下以一个 max_heap 为底层,后者以一个 vector 表现的完全二叉树实现。
- 只允许在底端加入元素,在顶端取出元素。
- 带有权值观念,其内的元素并非按照进入的次序排列,依照元素的权值排列。
- STL priority_queue 往往不归为 container 容器,而归为 container adapter。
2. priority_queue 提供 empty、size、top、push、pop 等算法。