动态数组是众所周知的数据结构:例如,我们为8个元素分配一个数组,并在插入数组末尾时使用这些插槽。当我们没有插槽时,我们会分配一个大小为16的数组,依此类推。我们得到O(1)
分摊插入到最后的复杂性。动态数组以许多语言及其标准库实现。
这里的一个限制是插入到数组的开头是O(n)
,因为开头没有空闲的插槽。但是为什么不在数组的开头和结尾上都有一些空闲的插槽呢?它会在O(1)
的两端进行插入,如果我们两边的空闲插槽耗尽,我们就像往常一样分配一个更大的数组。
它将比一端动态阵列的内存效率更低(因为我们需要在两侧保持空闲的插槽),但在双方都插入O(1)
并不是一个糟糕的权衡。或者是吗?还有其他缺点吗?我还没有看到这个数据结构在任何地方实现,它的致命缺陷是什么?
答案 0 :(得分:1)
这是我个人的看法。就像你说的那样,动态数组非常简单和普通,但它们在开头插入时肯定不会有很大的优势。你建议的东西,增加两端数组的大小,是一种可能性,也许它在某些情况下工作正常,但算法并不像它看起来那么清晰。在增长内部阵列时,是否总是在两端添加松弛或仅在已耗尽的一侧?或者你是否试图保持两个边距平衡?这可能会极大地影响结构的空间效率,这可能不容易预测。
另一方面,如果您需要在两端进行插入,则可以使用动态循环数组。圆形阵列的许多实现具有固定的最大大小,但没有什么能阻止您使其动态化。您甚至可以在一些动态数组实现之上实现它。循环数组引入了一个小的开销,即添加基本索引(无论如何都需要双端松弛)和计算模数,但它们具有可预测且节省空间的行为。
答案 1 :(得分:0)
实际上有些语言实现了这种数据结构,例如: C ++ STL中的deque。
deques的常见操作的复杂性(效率)如下 如下:
- 随机访问 - 常数O(1)
- 在结尾或开头插入或移除元素 - 常数O(1)
- 插入或移除其他元素 - 线性O(n)