【问题标题】:Are linked lists better than arrays for adding/removing elements at any position in the list?在列表中的任何位置添加/删除元素时,链表是否比数组更好?
【发布时间】:2019-06-02 12:28:13
【问题描述】:

我被告知,一般来说,从链表中添加和删除往往会更好,因为不必移动内存来容纳新元素。我不确定这是否真的适用于添加/删除可以在列表中的任何位置。

如果我是正确的,链表会这样操作;它会在O(n)时间内找到需要添加/删除的节点的位置,然后在O(1)内添加/删除节点,总时间为O(n)。

在一个数组中;由于随机存取内存,它会在 O(1) 时间内找到需要添加/删除的节点的位置,然后在 O(n) 时间内添加/删除节点,因为可能需要移动所有数据数组(假设删除意味着将所有节点移回 1)。从而给出O(n)的整体操作时间

由此看来,两者似乎都没有明显的优势。如果我查看平均情况,则链表平均会执行 n/2 次操作,因为节点平均位于列表的中间。

对于数组,出于类似原因,删除也需要平均 n/2 次操作,而如果需要移动所有数据以容纳额外元素,则添加将需要 n/2 次操作,如果有足够的空间并且需要将数据向上移动 1 个空间。这是否会给出 2*n/3 的平均值,这可能是为什么链表会更好的原因吗?

【问题讨论】:

  • 如果您无权访问节点本身,则两者都是 O(n)。链表需要 O(n) 来寻找节点,而数组需要 O(n) 来将剩余元素向左移动。
  • @WillemVanOnsem 所以两者都不是更好,因为我们不能再做任何假设了?
  • 如果索引与列表的大小相比通常较小,则链表会更好,如果索引更多位于列表末尾,则数组更好。
  • @WillemVanOnsem 嗯,这是一个额外的假设。似乎平均而言,数组的下界为 n/2,上界为 3n/4,而链表的平均值始终为 n/2。最好的情况是 O(1),所以这不太有用。
  • 您的里程会有所不同,但请记住,数组比链表对缓存更友好。 Herb Sutter 做了一个精彩的演讲,他谈到了这个:youtube.com/watch?v=TJHgp1ugKGM(如果你想了解好东西,请跳到大约 29:27)。

标签: arrays algorithm linked-list


【解决方案1】:

欢迎来到 SO!有趣的问题。
我认为你是对的,只要数组可以扩展,这两个操作都是 O(n),而不分配新的内存。
但如果必须分配新的内存,问题是接下来会发生什么。
在您的问题中,您假设必须为新的全尺寸数组分配内存。但这可能不是真的。
我不是操作系统专家,但我可以想象以下情况:
内存被划分为页面。如果当前 nr 页 (n) 不足以在插入后存储新数组,则新数组需要 n+1 页。
在这种情况下——如果我是一名操作系统程序员——我不会分配新的 n+1 页并将具有 O(n) 的整个数组复制到新内存,但我会再分配一页,并设置虚拟使旧页和新页在虚拟内存中是连续的,即使它们在物理内存中是不连续的。 在这种情况下,情况与不必分配新内存相同(考虑 O 表示法)。
简而言之,我相信这两种实现都是 O(n)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-02
    • 2021-01-24
    • 2015-09-20
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 2015-06-12
    • 2019-03-22
    相关资源
    最近更新 更多