【问题标题】:How to minimize visual width of (binary) search tree?如何最小化(二进制)搜索树的视觉宽度?
【发布时间】:2013-11-13 00:01:58
【问题描述】:

简介

我正在构建一个 HTML5 Web 应用程序,它根据给定的数字列表创建二叉搜索树的可视化表示。

目前,我有一个算法,它根据树的最大深度(以 0 为底的值)计算每行节点之间的视觉间距:

offset = 50
offset *= pow(2, maxDepth - currentDepth)

从这里开始,节点的位置是使用这个偏移量和它的父节点的 x 位置来确定的。

该算法运行良好,因为它始终能够适应任何深度的最宽树。但是,这有时也会使树变得不必要地宽。

示例

向左分支的树(太宽):

Tree branching to the left http://f.cl.ly/items/0c0t0L0L0o411h092G2w/left.png

向两侧分枝(左右两侧可以更靠近)。

Tree branching to both sides http://f.cl.ly/items/0r3X1j0w3r1D3v1V1V3b/left-right.png

理想情况下,上面的树应该是一个金字塔形,宽度较小,边是直的,如下图所示:

平衡树(算法效果最好的情况):

Balanced tree http://f.cl.ly/items/203m2j2i3P1F2r2T3X02/balanced.png

实施

属性

我正在使用 Backbone.js 从 Node 模型创建节点。每个节点都有以下属性:

  • parent(父节点)
  • left(左子节点)
  • right(右子节点)
  • x(节点的 x 位置,以像素为单位)
  • y(节点的 y 位置,以像素为单位)

上面的 xy 属性是根据节点分支的方向计算得出的:

if (parent.get('left') === node) {
    x = parentX - offsetX;
    y = parentY + offsetY;
} else if (parent.get('right') === node) {
    x = parentX + offsetX;
    y = parentY + offsetY;
}

此时,xy 属性是用于定位节点的确切值(每个都在容器元素中绝对定位)。

方法

  • getDepth()(返回节点的base-0深度)
  • getMaxDepth()(返回树中最后一行的深度)
  • getRow(n)(返回深度为 n 的所有节点的数组)

问题

因此,我的问题很简单:

最小化二叉树美学宽度的最佳算法是什么?

【问题讨论】:

  • 你的树到底长什么样,平衡吗?也许你应该举个例子
  • 好主意;我现在添加了一些示例。
  • 您应该检查每个级别有多少个节点并获得最大值,以便您可以选择图形的宽度。然后使用自下而上的方法来放置节点。如果您可以发布您的数据结构(最好是 JSON),我们可以使用特定的 js 代码而不是抽象算法来回答。
  • 在您的第三个示例(具有五个节点的示例)中,如果不是从根节点开始的两个节点的两个长分支,那么理想的布局是什么?
  • 好的,我已经添加了有关我的数据结构的更多细节,以及理想场景的图片。

标签: javascript algorithm binary-tree spacing graph-visualization


【解决方案1】:

您可以使用 AVL 树。这些插入时的自我平衡在每次插入后为您提供平衡的树。

http://en.wikipedia.org/wiki/AVL_tree

【讨论】:

  • 问题(现在)是:给定一棵特定的树(不一定是平衡的),如何最好地可视化它?我觉得这个答案不合适。
【解决方案2】:

如果您查看a similar question 的答案,它会对您有所帮助;它们包含指向软件的链接,这些链接正是您想要的那种树状可视化。


美学是高度主观的,所以这只是我的看法。我认为我的准则(不是算法)如下。我假设孩子的顺序很重要(因为这些是二叉搜索树)。

  1. 只有x 坐标是有趣的; y 坐标只能由节点的级别确定。 (如果违反这一点,我会觉得很丑陋,但正如我所说,口味不同。但是,其余的都是基于这个假设。)

  2. 同一级别中的任何节点都不应比某个固定的最小距离更近(例如D)。

  3. 如果一个节点在x1x2 有两个子节点,我希望它被放置在(x1+x2)/2。在某些情况下,最好选择[x1..x2] 中的某个其他坐标(可能是它的一端)。我想可能会有一些不寻常的情况,在 [x1..x2] 之外的坐标会更可取。

  4. 1234563 )。在某些情况下,最好偏离这个并在[xp..x1](甚至外部)中选择一些其他坐标。
  5. 让我们将级别的 width 称为最左边和最右边节点之间的距离。最宽层的宽度应该是最小的。

这些准则施加了无法同时满足的约束。因此,您应该优先考虑它们,这又是主观的。例如,更重要的是#4 还是#5?您对 5 节点树的草图暗示#4 更重要;如果#5 更重要,您将获得类似房屋的图片(垂直线);如果两者都很重要,那么您当前的结果会很好。

解决此问题的一种方法是为准则分配权重,并在不遵守这些准则时确定处罚。例如,在准则 #3 中,如果父级位于x 而不是位于其子级之间的中间,则可以使用abs(x-(x1+x2)/2) 进行惩罚;与其他指南相比,您还可以分配一个权重,告诉您这是多么重要。然后,您应该尝试最小化解决方案的总加权惩罚。一般来说,这会给你一个constraint optimization problem,有几种方法可以解决这些问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    • 2011-02-18
    • 2016-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多