【问题标题】:Effective implementation of list of lists清单清单的有效执行
【发布时间】:2015-11-12 18:41:06
【问题描述】:

我正在尝试实现一个列表列表,其中:

  • 外部列表的大小已知(例如 N)
  • 每个元素列表可以不同并在运行时确定的大小。

一个简单的实现如下:

L = [[] for x in range(N)]

然后在数据进来时更新L[i]

L[i] = range(M)

但这会占用大量内存,因为如果元素列表不适合当前位置,python 必须将整个列表复制到新位置。

我相信解决方案是使用链表作为外部列表,但由于 Python 中缺少预定义的链表实现,我想知道还有另一种解决方案吗?

【问题讨论】:

  • 为什么要复制整个列表才能为一个元素设置值?
  • L[i] 作为L[i].appendL[i][j] = something 之类的列表访问没有任何问题,而无需复制整个列表......
  • @Two-BitAlchemist @R-Nar 不要忘记每个元素(这是一个列表)的大小是不同的和变化的。如果元素(内部列表)不适合python,我每次设置L[i](外部列表)都会将整个事物移动到新位置。或者至少这是我对正在发生的事情的理解。
  • @MBZ 是的,每次预分配的数组超出其初始大小时,都必须调整其大小。这是动态数组的一部分。对我来说(我可能会误解),答案似乎是在内部列表到来时填充它们,而不是预先分配一个必须多次调整大小的外部列表。
  • 在实践中,CPython 将分配比它需要的更多的空间,这样它就不必在每次append 时移动/调整列表大小。 IIRC 只要超出容量,它就会将列表的内部大小加倍,因此摊销效率实际上是 O(1)。这似乎是在遇到实际瓶颈之前寻找优化的案例。

标签: python list linked-list


【解决方案1】:

Python 不会将子列表存储在外部列表中;它只存储对外部列表内子列表的引用。重新分配内部列表永远不需要复制外部列表;在实现层面,它只不过是一个单一的指针赋值。

如果您熟悉 C# 或 Java,您会熟悉的术语是 everything 是 Python 中的引用类型。如果您熟悉 C++,可以将其视为在 vector<vector<int>> 中调整内部向量的大小不会调整外部向量的大小。

【讨论】:

    猜你喜欢
    • 2011-06-23
    • 2015-03-10
    • 1970-01-01
    • 2019-04-29
    • 2011-07-21
    • 2014-02-08
    • 1970-01-01
    • 1970-01-01
    • 2021-12-16
    相关资源
    最近更新 更多