为什么要加倍堆叠容量而不是仅按固定数量增加容量?

时间:2012-05-02 18:05:57

标签: arrays stack

我正在使用堆栈的数组实现,如果堆栈已满而不是抛出错误我将数组大小加倍,复制元素,更改堆栈引用并将新元素添加到堆栈。 (我正在读一本书来教我自己的东西)。

我不完全理解的是为什么我应该加倍,为什么不将它增加一定数量,为什么不将它增加3倍。

我认为它与时间复杂性有什么关系?

非常感谢您的解释!

4 个答案:

答案 0 :(得分:3)

Doubling刚刚成为数组列表(“动态”大小的数组,实际上只是在后台执行的操作)以及由数组支持的大多数动态大小的数据类型之类的通用实现的标准。如果您了解自己的场景并且有时间和意志来编写自定义堆栈/阵列列表实现,那么您当然可以编写更优的解决方案。

如果您在软件中知道在构建初始数组后不经常添加项目,您可以使用特定大小初始化它,然后只增加它所添加的大小以保留内存。

另一方面,如果您知道列表会经常扩展,那么当空间不足时,您可能会选择将列表大小增加3倍或更多。

对于作为公共库的一部分的通用实现,您的实现细节和要求是未知的,因此加倍只是一种快乐的媒介。

答案 1 :(得分:2)

理论上,你确实达到了不同的时间复杂性。如果增加一个常量,则将重新分配的数量(以及O(n)副本)除以常量,但仍然可以获得O(n)时间复杂度以进行追加。如果你加倍它们,你会得到一个更好的时间复杂度来附加(armortized O(1)IIRC),并且你最多只需要两倍的内存消耗,你仍然可以获得相同的空间复杂度。

在实践中,它不那么严重,但仍然可行。副本很昂贵,而一点内存通常不会受到伤害。这是一个权衡,但你必须在内存上相当低,才能选择其他策略。通常,您事先不知道(或者由于API限制而无法让堆栈知道)您实际需要多少空间。例如,如果你构建一个以一个元素开头的1024个元素堆栈,你可以得到(我可能会被一个人关闭)10个重新分配,从1024 / K开始 - 假设K = 3,这大约是34倍许多重新分配,只是为了节省一点内存。

同样适用于任何其他因素。 2很不错,因为你永远不会得到非整数大小,它仍然很小,将浪费的空间限制在50%。其他因素可能更好地满足特定用例,但通常ROI太小,无法重新实施和优化某些库中已有的用途。

答案 2 :(得分:1)

固定金额的问题是选择固定金额 - 如果您(比方说)选择100项作为固定金额,那么如果您的筹码目前大小为100件,则有意义。但是,如果您的堆栈大小已经是10,000个项目,则可能增长到11,000个项目。您不希望进行10次重新分配/移动,以使堆栈大小增加10%。

至于2x与3x,这是非常随意的 - 选择3x并没有错;哪个“更好”将取决于您的确切用例以及您如何定义“更好”。

答案 3 :(得分:0)

缩放2倍很容易,并且将确保平均项目被复制不超过两次[扩展将首次复制一半项目,第二次复制四分之一,第三次复制八分之一等]如果事情增长了固定的数量,那么当例如进行了第二十次扩展,一半的项目将被复制第十次。

增长超过2倍会增加平均值"永久性"松弛的空间;通过较小的因子增长将增加分配和放弃的存储量。取决于相对感知"成本"对于永久性和放弃的分配,最佳生长因子可能更大或更小,但是接近最佳值的生长因子通常不会比最佳生长因子差得多。。无论最佳增长因素是什么,2倍的增长因子都足够接近,以产生不错的表现。