C++ std::vector中push_back操作时间复杂度分析

 vectorSTL中的一种序列式容器,采用的数据结构为线性连续空间,它以两个迭代器 start 和 finish 分别指向配置得来的连续空间中目前已被使用的范围,并以迭代器end_of_storage 指向整块连续空间(含备用空间)的尾端,结构如下所示:

    template Alloc = alloc>

    class vector {

  ​  ...

    protected:

        iterator start;                     // 表示目前使用空间的头

        iterator finish;                   // 表示目前使用空间的尾

        iterator end_of_storage;  // 表示可用空间的尾​

     ...};​

我们在使用 vector 时​,最常使用的操作恐怕就是插入操作了(push_back),那么当执行该操作时,该函数都做了哪些工作呢?

该函数首先检查是否还有备用空间,如果有就直接在备用空间上构造元素,并调整迭代器 finish,使 vector变大。如果没有备用空间了,就扩充空间,重新配置、移动数据,释放原空间。​

 其中​判断是否有备用空间,就是判断  finish是否与 end_of_storage 相等.如果 

finish != end_of_storage,说明还有备用空间,否则已无备用空间。

当执行 push_back 操作,该 vector 需要分配更多空间时,它的容量(capacity)会增大到原来的 倍。​现在我们来均摊分析方法来计算 push_back 操作的时间复杂度。

假定有 n 个元素,倍增因子为 m。那么完成这 n 个元素往一个 vector 中的push_back​操作,需要重新分配内存的次数大约为 logm(n),第 i 次重新分配将会导致复制 m^i (也就是当前的vector.size() 大小)个旧空间中元素,因此 n 次 push_back操作所花费的总时间约为 n*m/(m - 1):

时间复杂度计算

很明显这是一个等比数列.那么 n 个元素,n 次操作,每一次操作需要花费时间为 m / (m - 1),这是一个常量.

所以,我们采用均摊分析的方法可知,vector 中 push_back 操作的时间复杂度为常量时间.​

参考资料:

《STL源码剖析》侯捷 著

​ http://cs.stackexchange.com/questions/9380/why-is-push-back-in-c-vectors-constant-amortized


原文链接

阅读更多

没有更多推荐了,返回首页