vector 这个我们最熟悉了,也可能是我们用的最多的容器之一了。
我们可以用vector来模拟栈,vector的push_back和pop_back效率很高,时间复杂度是常数。
由于他是一个连续的内存区域,所以他能够随机访问容器中的人一个元素且时间复杂度也是常数。
但是vector是一个不能够自动“减肥”的容器。比如一开始你在push_back很多元素后,然后再某一个时间点释放点这些元素,虽然vector的size为0,但是vector的capacity却始终很大,这一点和浪费空间。在一些对时间和空间要求比较高的情况下,vector的push_back和pop_back以及它的随机访问能力很强,但是它在空间利用方面却不是很理想。
比如我们想要一个vector的利用率达到50%。我们可以这样做:
if(vec.size() < vec.capacity() >> 1 ) {
vector<int> vectmp(vec);
vectmp.swap(vec);
}
其实vector对插入(非尾部)和删除(earse)是很费效率的,一般情况下不要对vector进行插入和删除操作,对vector的插入/删除都会引起vector内部插入点以后的元素整体向后/向前移动。对vector的insert/earse会引起除begin和end(不能访问到)之外的iterator失效,所以最好不要在循环一个vector的时候删除vector里边的元素,否则迭代器会失效,那该怎么呢?可以使用下标访问。
list其实也是我们接触最多的之一,链表分为单向链表,双向链表,循环链表,在这里就不说他们之间的区别了,主要从效率方面。
list的不足,它不像vector一样拥有连续的存储空间,所以它不能实现随机访问,要想访问也可以必须一个一个的去寻找。
它相对vector拥有额外的开销就是指向前一个和后一个的指针。
但是list也有自身的好处,它对随机插入删除的效率可比vector高很多,他的插入删除的时间复杂度为常数。
他的空间利用率也很高,特别是存储大对象,他不想vector,他删除一个元素就删除该元素的实际空间。