树:链表与数组(效率)
Posted
技术标签:
【中文标题】树:链表与数组(效率)【英文标题】:Trees: Linked Lists vs Arrays (Efficiency) 【发布时间】:2010-02-08 08:06:27 【问题描述】:这是一个作业问题,我很难回答。
“假设一棵树的每个节点最多可以有 k 个子节点。设 v 是每个节点的平均子节点数。对于 v 的什么值,存储子节点更有效(就使用的空间而言)链表中的节点与数组中的存储?为什么?"
我相信我可以回答“为什么?”或多或少地用简单的英语 - 使用链表会更有效,因为不是有一堆空节点(即如果你的平均值低于最大值,则数组中的空索引)占用内存你只分配空间当您实际填写一个值时,对于链表中的一个节点。
因此,如果在最大值为 200 时平均有 6 个子节点,则该数组将在创建树时为每个节点的所有 200 个子节点创建空间,但链表只会为节点分配空间如所须。因此,使用链表,使用的空间大约是(?)平均值;使用数组,使用的间隔将是最大值。
...我不知道什么时候使用数组会更有效。这是一个技巧问题吗?我是否必须考虑到数组在创建时需要对节点总数进行限制这一事实?
【问题讨论】:
【参考方案1】:对于许多常用语言,数组将需要分配存储k 个内存地址(数据的)。单链表每个节点需要 2 个地址(数据和下一个)。双向链表每个节点需要 3 个地址。
令n为特定节点A的实际子节点数:
数组使用 k 个内存地址 单链表使用 2n 个地址 双向链表使用 3n 个地址k 值允许您确定 2n 或 3n 个地址与仅存储数组中的地址。
【讨论】:
【参考方案2】:...我不知道什么时候使用数组会更有效。这是一个棘手的问题吗?
这不是一个技巧问题。想想链表的内存开销。链表是如何实现的(相对于数组)?
此外(尽管这超出了问题的范围!),空间消耗并不是实践中的唯一决定因素。缓存在现代 CPU 中发挥着重要作用,将各个子节点存储在数组而不是链表中可以显着提高缓存局部性(从而提高树的性能)。
【讨论】:
我不确定您所说的链表开销是什么意思。您是在谈论引用所需的内存吗? @dc:那么,链表是如何实现的?需要多少内存?【参考方案3】:数组必须预先分配空间,但我们可以使用它们快速访问任何条目。 列表在创建新节点时分配内存,这并不理想,因为 CPU 时间的内存分配成本。
提示:如果您愿意,您可以一次分配整个数组,但通常我们会分配, 假设有 4 个条目,当我们需要更多空间时,我们通过将大小加倍来调整它的大小。
【讨论】:
这个问题只是关于空间,而不是关于时间。 @Konrad Rudolph,确实如此。由于“我不知道什么时候使用数组会更有效”,我提到了一个提示:)【参考方案4】:我可以想象在许多情况下使用LinkedList
可能是一个非常好的主意并且非常有效,如果一个使用的数据项无论如何都具有前一个和下一个项目的内在逻辑,例如TimeTableItem
或任何东西这在某种程度上与时间有关。这些应该实现一个接口,因此LinkedList
实现可以利用它并且不必将项目包装到它自己的节点对象中。在这里插入和删除比使用在内部处理数组的List
实现更有效。
【讨论】:
【参考方案5】:您假设无法动态重新分配数组。如果可以,则数组获胜,因为它不需要大于 k 个项目(加上恒定的开销),并且不需要为每个项目存储指针。
【讨论】:
以上是关于树:链表与数组(效率)的主要内容,如果未能解决你的问题,请参考以下文章