为什么vector的capacity是按照2的指数来长的?
结论
为了让push_back的均摊(amortized)时间复杂度为常数时间。
基础
首先我们都知道vector在size超过capacity的时候,会另寻2倍于capacity的堆空间,然后把原来的数据搬移到新空间上,再释放旧空间。在这个过程中,将原有的数据搬移到新空间是比较费时的操作,平均时间复杂度是O(n)。
在容量够用的时候,push_back的时间复杂度是O(1),这个没什么疑问。在容量不够用,需要搬移的时候,push_back的时间复杂度就是O(n)了。那么均摊时间复杂度是O(1)是怎么来的呢?
分析
假设有一个vector,长度从0经过若干次push_back增长为n,且增长因子为m,也就是说capacity是按m倍数增长的。那么一共需要logm(n)次数据搬移,并且第i次(0<i<logm(n))次搬移的成本是m的i次方。
将以上的所有搬移的代价加起来,会得到这个类似于等比数列的和:
总代价 = m + pow(m, 2) + pow(m, 3) + ... + pow(m, logm(n)) ≈ m*n/(m-1)
简单算一下,可以知道这个总代价是和n一个量级的。所以push_back的均摊(amortized)时间复杂度为与n无关的常数时间m/(m-1)。所以增长因子m的选择很重要,m太接近1,(当然必须大于1),就会导致均摊的时间复杂度过高,m太偏离1,就会浪费太多内存。据我所知不同版本的STL有选择2的,也有选择1.5的。