【问题标题】:What are the disadvantages of double ended dynamic array data structure?双端动态数组数据结构的缺点是什么?
【发布时间】:2017-12-04 10:40:01
【问题描述】:

动态数组是一种众所周知的数据结构:例如,我们分配一个包含 8 个元素的数组,并在插入到数组末尾时使用这些插槽。当我们没有插槽时,我们分配一个大小为 16 的数组,依此类推。我们得到O(1) 插入到末尾的摊销复杂性。动态数组以多种语言及其标准库实现。

这里的一个限制是插入到数组的开头是O(n),因为开头没有空闲插槽。但是为什么不在数组的开头和结尾都设置一些空闲槽呢?它可以在两端插入O(1),如果我们用完任一侧的空闲插槽,我们会像往常一样分配一个更大的数组。

它的内存效率将低于单端动态数组(因为我们需要在两侧维护空闲插槽),但在两侧插入 O(1) 并不是一个糟糕的权衡。或者是吗?还有其他缺点吗?我还没有看到这种数据结构在任何地方实现,它的致命缺陷是什么?

【问题讨论】:

  • 我猜这取决于算法,如果您的算法要求您同时执行追加和前置操作,那么这种数据结构可能会给您带来一些好处。即使在这种情况下,跟踪最后一个元素的链表也可能更易于使用。
  • @Ankur 链表会更简单,但这里我也有O(1) 随机索引访问。
  • 我猜大多数算法只是不需要在开头经常插入。 grep 一些 Python 代码库,并计算 append 的数量与 insert(0, 的数量。所以大多数人只是懒得去创造它。

标签: arrays algorithm data-structures dynamic-arrays


【解决方案1】:

这是我个人的看法。就像你说的,动态数组非常简单和普通,但它们在开始时的插入肯定不会有很好的表现。像您建议的那样,增加两端数组的大小是可能的,在某些情况下它可能工作正常,但算法并不像看起来那么清晰。在增加内部阵列时,您总是在两端添加松弛还是仅在已用尽的一侧添加松弛?或者你是否试图保持两个利润平衡?这可能会极大地影响结构的空间效率,而且可能不容易预测。

另一方面,如果您需要在两端插入,您可以使用动态循环数组。循环数组的许多实现都有一个固定的最大大小,但没有什么能真正阻止你让它成为动态的。您甚至可以在一些动态数组实现之上实现它。循环数组引入了添加基本索引(在双端松弛时无论如何都需要)和计算模数的少量开销,但它们具有可预测且节省空间的行为。

【讨论】:

    【解决方案2】:

    实际上有些语言已经实现了这种数据结构,例如deque 在 C++ STL 中。

    deques 上常见操作的复杂度(效率)为 如下:

    • 随机访问 - 常数 O(1)
    • 在末尾或开头插入或删除元素 - 常数 O(1)
    • 插入或移除其他元素 - 线性 O(n)

    【讨论】:

    • std::deque 具有相同的属性,但实现更复杂。它是向量的向量,而不是一个数组。
    猜你喜欢
    • 2012-02-18
    • 2012-01-27
    • 2017-07-12
    • 1970-01-01
    • 2020-10-15
    • 2015-03-17
    • 2013-06-03
    • 1970-01-01
    • 2021-09-17
    相关资源
    最近更新 更多