【问题标题】:Most performant way to find all the leaf nodes in a tree data structure在树数据结构中查找所有叶节点的最高效方法
【发布时间】:2017-10-07 18:09:18
【问题描述】:
我有一个树数据结构,其中每个节点可以有任意数量的子节点,并且树可以是任意高度。获取树中所有叶节点的最佳方法是什么?是否有可能比只遍历树中的每条路径直到我碰到叶子节点做得更好?
实际上,树的最大深度通常为 5 左右,树中的每个节点将有大约 10 个子节点。
我对其他类型的数据结构或特殊树持开放态度,这些数据结构或特殊树会使叶节点特别优化。
我正在使用 javascript,但实际上只是在寻找一般建议,任何语言等。
谢谢!
【问题讨论】:
标签:
algorithm
performance
optimization
tree
【解决方案1】:
内存布局对于最佳检索至关重要,因此子列表应该是连续的而不是链表,节点应该按检索顺序依次放置。
你的树越静态,布局就越好。
多合一布局
完全有序的一个数组
-
专业版
- 内存可以流式传输以获得最大吞吐量(硬件预取)
- 没有不需要的页面查找
- 可以正常查找
- 没有额外的内存来创建链表。
- 内部节点使用偏移量来查找相对于自身的子节点
-
骗子
- 插入/删除可能很麻烦
- 插入/删除 O(N)
- 插入可能会导致调整数组大小,从而导致复制成本高昂
两个数组布局
- 一个用于内部节点的数组
- 一个叶子数组
内部节点指向叶子
-
专业版
- 叶节点可以以最大吞吐量进行流式传输(如果您主要只对叶感兴趣,这可能是最佳布局)。
- 没有不需要的页面查找
- 可以进行间接查找
-
骗子
- 如果所有叶子都是有序的,插入/删除可能很麻烦
- 如果叶子是无序插入很容易,只需在末尾添加即可。
- 如果不允许墓碑删除无序叶子也是一个问题,因为最后一个叶子必须移回并且内部节点需要修复。 (通过进一步的间接,这也可以修复,参见 slot-map)
- 调整两者之一的大小可能会导致较大的副本,但小于一体机,因为它们可以独立完成。
数组数组(动态大小,C++ 向量向量)
- 使用连续数组来引用每个节点的子节点
- 专业版
- 骗局
- 虽然消除了链表子项的大部分额外工作,但单个列表分散在所有其他数据中,使得查找需要额外的时间。
- 插入可能会导致数组的大小调整和复制。
【解决方案2】:
查找树的叶子是O(n),这对于树来说是最优的,因为您必须查看O(n) 的位置来检索所有n 的东西,以及沿途的分支节点。恒定开销是分支节点。
如果我们增加分支因子,例如让每个分支有 32 个子节点而不是 2 个,我们显着减少了开销节点的数量,这可能会使遍历速度更快。
如果我们跳过一个分支,我们不包括该分支中的值,所以我们必须查看所有分支。