2.3 动态空间管理
Posted nk-007
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2.3 动态空间管理相关的知识,希望对你有一定的参考价值。
空间管理方法主要分为两类:静态的和动态的。顾名思义,静态空间管理即是在向量生命期内,其内部数组所占物理空间的容量不允许增加,这种策略既拘泥固化且空间管理效率底下,因此常采取动态空间管理策略,具体方法是使向量可扩充。
可扩充向量既能够在空间不足达到上溢临界点时扩充向量空间,同时能够在空间需求不甚强烈,达到下溢临界点时缩容空间向量。
扩容
对向量实现扩容的难点在于如何实现扩容?新的容量取作多少才算适宜?
如何扩容?——先保留,再扩容,后迁移。
因为向量是寻秩访问,上下秩之间物理地址连续,所以在扩容的过程中必须保证物理空间必须地址连续,所以可行的方法是:通过申请更大容量的内部数组,将原先内部数组中的成员集体搬迁到新的空间,此后方可顺利地插入新元素e而不致数据溢出。原数组所占空间及时释放,并归还操作系统。实现代码如下:
template <typename T> void Vector<T>::expand() {
if (_size < _capacity)
return;
if (_capacity < DEFAYLT_CAPACITY)
_capacity = DEFAYLT_CAPACITY;//使其不小于默认容量即最小容量
T* oldElem = _elem;
_elem = new T[_capacity <<= 1];//容量加倍
for (int i = 0; i < _size; i++)
_elem[i] = oldElem[i];//复制原向量内容
delete[] oldElem;
}
有趣的是,最调用insert()接口插入新元素之前,都要先调用该算法用于检查数组容量。
缩容
当向量的规模远远小于内部数组的容量,称为下溢时,我们会采取缩容操作。具体算法如下:
template <typename T> void Vector<T>::shrink() {
if (_capacity < DEFAYLT_CAPACITY << )
return;
if (_size << 2 > _capacity)
return;
T* oldElem = _elem;
_elem = new T[_capacity >>= 1];//容量加倍
for (int i = 0; i < _size; i++)
_elem[i] = oldElem[i];//复制原向量内容
delete[] oldElem;
}
当我们分析通过直接扩容两倍的方式来分析扩容向量复杂度时,采取的具体尺度是分摊复杂度。
所谓分摊复杂度和相关的分摊运行时间,其参与分摊的操作必须构成和来自一个真实可行的操作序列,且足够长。这与传统的平均运行时间有着本质的区别,后者是按照某种假定的概率分布,对各种情况下所需执行时间的加权平均,亦称期望运行时间。
对于本文中所采取的两倍扩容操作,所需时间为O(n)。
以上是关于2.3 动态空间管理的主要内容,如果未能解决你的问题,请参考以下文章