vector扩容原理说明
来源:互联网 发布:加拿大软件培训 编辑:程序博客网 时间:2024/06/06 00:02
扩容原理概述
- 新增元素:Vector通过一个连续的数组存放元素,如果集合已满,在新增数据的时候,就要分配一块更大的内存,将原来的数据复制过来,释放之前的内存,在插入新增的元素;
- 对vector的任何操作,一旦引起空间重新配置,指向原vector的所有迭代器就都失效了 ;
- 初始时刻vector的capacity为0,塞入第一个元素后capacity增加为1;
- 不同的编译器实现的扩容方式不一样,VS2015中以1.5倍扩容,GCC以2倍扩容。
代码
#include<iostream>#include<vector>using namespace std;int main(){ vector<int> vec; cout << vec.capacity() << endl; for (int i = 0; i<10; ++i) { vec.push_back(i); cout << "size: " << vec.size() << endl; cout << "capacity: " << vec.capacity() << endl; } system("pause"); return 0;}
输出:
- GCC输出
- VS2015输出
分析:
- 可以根据输出看到,vector是以2倍的方式扩容的。这里让我产生了两个疑问:
- 为什么要成倍的扩容而不是一次增加一个固定大小的容量呢?
- 为什么是以两倍的方式扩容而不是三倍四倍,或者其他方式呢?
- 第一个问题:
- 以成倍方式增长
- 假定有 n 个元素,倍增因子为 m;
- 完成这 n 个元素往一个 vector 中的 push_back操作,需要重新分配内存的次数大约为 logm(n);
- 第 i 次重新分配将会导致复制 m^(i) (也就是当前的vector.size() 大小)个旧空间中元素;
- n 次 push_back 操作所花费的时间复制度为O(n):
- m / (m - 1),这是一个常量,均摊分析的方法可知,vector 中 push_back 操作的时间复杂度为常量时间.
- 一次增加固定值大小
- 假定有 n 个元素,每次增加k个;
- 第i次增加复制的数量为为:100i
- n 次 push_back 操作所花费的时间复杂度为O(n^2):
- 均摊下来每次push_back 操作的时间复杂度为O(n);
- 以成倍方式增长
- 总结:对比可以发现采用采用成倍方式扩容,可以保证常数的时间复杂度,而增加指定大小的容量只能达到O(n)的时间复杂度,因此,使用成倍的方式扩容。
- 第二个问题:
- 根据查阅的资料显示,考虑可能产生的堆空间浪费,成倍增长倍数不能太大,使用较为广泛的扩容方式有两种,以2二倍的方式扩容,或者以1.5倍的方式扩容。
- 以2倍的方式扩容,导致下一次申请的内存必然大于之前分配内存的总和,导致之前分配的内存不能再被使用,所以最好倍增长因子设置为(1,2)之间:
- 知乎上看到一个很好的解释:
C++ STL中vector内存用尽后,为啥每次是两倍的增长,而不是3倍或其他数值? - 借用他的一张图来说明2倍与1.5倍的区别:
总结
- vector在push_back以成倍增长可以在均摊后达到O(1)的事件复杂度,相对于增长指定大小的O(n)时间复杂度更好。
- 为了防止申请内存的浪费,现在使用较多的有2倍与1.5倍的增长方式,而1.5倍的增长方式可以更好的实现对内存的重复利用,因为更好。
参考
- C++ STL中vector内存用尽后,为啥每次是两倍的增长,而不是3倍或其他数值?
- 《STL系列》之vector原理及实现
- vector中push_back操作时间复杂度分析
PS
- 本人水平有限,文中难免会出现一些错误,欢迎指正,探讨。^^
0 0
- vector扩容原理说明
- vector扩容
- vector的自动扩容
- ArrayList、Vector、HashMap、HashSet的默认初始容量、加载因子、扩容增量底层原理
- c++STL vector扩容过程
- vector扩容问题源代码剖析
- ArrayList 原理、 扩容机制
- HashMap扩容原理
- XX图文扩容配置说明
- ArrayList和Vector的扩容机制
- ArrayList、Vector、HashMap、HashTable是如何扩容
- ArrayList、Vector、HashMap、HashTable是如何扩容
- ArrayList和Vector的扩容机制
- ArrayList和Vector的扩容机制
- vector扩容2倍与1.5倍
- ArrayList和Vector的扩容机制
- ArrayList、Vector、HashMap、HashTable是如何扩容
- ArrayList的add()扩容原理
- 非JAVA程序员如何转型为一名优秀的JAVA工程师
- 谈谈对AIO、BIO和NIO的理解
- 两种共享内存的实现区别,shm和mmap
- 数理统计——有1,2,3,......无穷个格子,你从1号格子出发,每次1/2概率向前跳一格,1/2概率向前跳两格,走到格子编号为4的倍数时结束,结束时期望走的步数为
- KMP算法java实现
- vector扩容原理说明
- Project configuration is not up-to-date with pom.xml. Run Maven->Update Project or use Quick Fix
- oracle的几种备份区别!
- H5新增表单输入项
- poj--3067 Japan(树状数组+逆序数)
- RaspberryPi之软件组件和启动流程介绍
- 51nod oj 1366 贫富差距【枚举+最长的短路】
- android:layout_gravity="right"控制LinearLayout中控件居右显示失败
- Pop Sequence