各个容器的优缺点
容器类型 | 优点 | 缺点 |
vector |
| 1)插入删除效率慢 2)不支持在头部push和pop |
deque |
|
|
list | 1)插入和删除效率高(常数时间) 2)每个节点独立存储 | 1)不支持随机访问 2)相对于vector占用的内存多 |
set |
| 1)占用内存大 2)和元素的插入顺序无关 |
map | 1)自动排序,查找效率高 2)每个节点独立存储 | 1)占用内存大 2)和元素插入顺序无关 |
-
关于容器使用的建议
- 如果没有特别的原因,优先使用vector而不是deque。
- 使用vector时,如果知道vector要存储的元素数量,可以通过reserve函数来获取足够的空间,防止vector空间不足而导致重新申请-拷贝-释放。
- 使用vector时,如果想删除多余的空间,可以通过v1.swap(vector<T>(v1)),释放没有使用的空间。
- 使用线性容器时,注意迭代器的失效问题。
- set和map的优点是自动排序,这样其查找效率很高。但如果数据本身就是有序的,可以考虑使用vector来存储数据,并通过二分查找法来查找元素,其效率更高,占用内存更低。
-
迭代器失效问题
(1)增加元素到容器后
对于vector和string,如果容器内存被重新分配,iterators、pointers、references失效;如果没有重新分配,那么插入点之前的iterator有效,插入点之后的iterator失效;
对于deque,如果插入点位于除front和back的其它位置,iterators、pointers、references失效;当我们插入元素到front和back时,deque的迭代器失效,但reference和pointers有效;
对于list和关联容器,所有的iterator、pointer、reference有效。
(2)从容器中移除元素后
对于vector和string,删除点之前的iterators、pointers、references有效;off-the-end迭代器总是失效的;
对于deque,如果插入点位于除front和back的其它位置,iterators、pointers、references失效;当我们插入元素到front和back时,off-the-end失效,其他的iterators、pointers、references有效;
对于list和关联容器,除了删除点,所有的iterator、pointer、reference有效。
(3)在循环中refresh迭代器
当处理vector、string、deque时,当在一个循环中可能增加或移除元素时,要考虑到迭代器可能会失效的问题。我们一定要refresh迭代器。
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
deque<int> v(arr,arr+sizeof(arr)/sizeof(*arr));
for (auto it = v.begin(); it != v.end(); )
{
if ((*it) & 1)
{
it = v.insert(it, *it);
it += 2;
}
else
it = v.erase(it);
}
到此,我们基本学完了STL容器的使用,然后只会使用容器,而不能熟练掌握STL提供的算法,那就不能发挥STL的威力。STL的标准容器不到10个,而其提供的算法有100个左右,可见其算法功能大多样性。下面我们将进入算法的学习时间。