[英]How to minimize visual width of (binary) search tree?
我正在构建一个HTML5 Web应用程序,它从给定的数字列表中创建二叉搜索树的可视化表示。
目前,我有一个算法,根据树的最大深度(这是一个基数为0的值)计算每行节点之间的视觉间距:
offset = 50
offset *= pow(2, maxDepth - currentDepth)
从这里开始,使用该偏移量和其父节点的x位置确定节点的位置。
该算法运行良好,因为它始终能够适应任何深度的最宽树。 然而,这也使得树有时不必要地宽。
树枝向左(太宽):
树枝向左分支http://f.cl.ly/items/0c0t0L0L0o411h092G2w/left.png
树枝分叉到两侧(左侧和右侧可以更靠近在一起)。
树枝分枝到两侧http://f.cl.ly/items/0r3X1j0w3r1D3v1V1V3b/left-right.png
理想情况下,上面的树应该像金字塔一样,宽度较小,边长,如下图所示:
平衡树(算法最佳的情况):
平衡树http://f.cl.ly/items/203m2j2i3P1F2r2T3X02/balanced.png
我正在使用Backbone.js从Node模型创建节点。 每个节点都具有以下属性:
上面的x和y属性是根据节点分支的方向计算的:
if (parent.get('left') === node) {
x = parentX - offsetX;
y = parentY + offsetY;
} else if (parent.get('right') === node) {
x = parentX + offsetX;
y = parentY + offsetY;
}
此时, x和y属性是用于定位节点的确切值(每个节点都位于容器元素内的绝对值)。
因此,我的问题很简单:
什么是最小化二叉树美学宽度的最佳算法?
如果你看一下类似问题的答案,它可以帮助你; 它们包含指向软件的链接,完全可以实现您想要的树形可视化。
美学是非常主观的,所以这只是我的观点。 我认为我的指南 (不是算法 )如下。 我假设孩子的顺序很重要(因为这些是二元搜索树)。
只有x
坐标很有趣; y
坐标应仅由节点的级别确定。 (如果这被违反,我会觉得相当丑陋,但正如我所说,口味不同。但其余的都是基于这个假设。)
同一级别的节点不应该比某个固定的最小距离(比如D
)更近。
如果节点在x1
和x2
处有两个子节点,我希望它放在(x1+x2)/2
。 在某些情况下,最好在[x1..x2]
选择一些其他坐标(可能是其一端)。 我想可能会出现异常情况,其中[x1..x2]
之外的坐标更可取。
如果一个节点在x1
处有一个子节点且其父节点在xp
,我希望它放在(x1+xp)/2
(因此它位于将其父节点连接到其子节点的行上)。 在某些情况下,最好偏离此并在[xp..x1]
(或甚至在外部)中选择一些其他坐标。
让我们将一个级别的宽度称为最左边节点和最右边节点之间的距离。 最宽的宽度应该是最小的。
这些指导规定了无法同时满足的约束。 因此,您应该优先考虑它们,这也是主观的。 例如,更重要的是,#4还是#5? 你对5节点树的草图暗示#4更重要; 如果#5更重要,你会得到一个像房子一样的画面(垂直线条); 如果两者都很重要,那么你目前的结果会很好。
解决这个问题的一种方法是为指南分配权重,并在未遵循这些权利的情况下定义处罚。 例如,在准则#3中,你可以用abs(x-(x1+x2)/2)
惩罚,如果父母被放置在x
,而不是在孩子之间; 与其他指南相比,您还可以指定一个重量,告诉您这是多么重要。 然后,您应该尝试最小化解决方案的总加权惩罚。 一般来说,这会给你一个约束优化问题 ,有几种方法可以解决这些问题。
您可以使用AVL树。 插入时的这些自我平衡可在每次插入后为您提供平衡的树。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.