如何绘制树形结构? (二维空间分配树递归算法?)

时间:2010-08-29 15:39:32

标签: algorithm data-structures graphics tree visualization

我有一个任意的节点树结构。我想绘制这个树,为用户提供可视化表示。我需要在树上进行递归,并为每个节点添加一个图形项到列表,然后只需在树递归完成后绘制项列表。项目的递归和绘制当然是微不足道的 - 如何定位图形节点以使它们不与其他分支重叠,这有点复杂。

我正在使用Android,但这并不重要 - 我正在寻找一种方法,可能是一种算法,可以在树空间经过树时保持2D空间的图像,因此它只为每个节点分配最合适的坐标因为它通过了。

有什么想法吗?

更新

This is the article with the best and most complete algorithm.

5 个答案:

答案 0 :(得分:4)

我建议按行绘制树。你可以通过使用某种移动的“绘图光标”来实现这一点。

您可以为每个节点存储属性width,其计算方法如下:

  • 请假的width为1
  • 内部节点的width是所有孩子的width的总和

然后,你在中间绘制根“在第一行”,这意味着你只需要生根width的一半。

然后,在图像上生成网格,使每个网格线对应一行resp。从左到右一步,网格线的每个交叉点都可以包含一个节点,每个节点都有足够的空间。

然后,您遍历子项并在迭代时,累积子项的width并在下一行中绘制子项“。要绘制currentChild,请将绘图光标currentWidth/2向右移动,绘制currentChild,然后将绘图光标移动到右侧的剩余currentWidth/2

为了使节点处于良好状态,您可以考虑进行广度优先搜索。

我希望我的解释清楚,但我认为如果我画一点照片会更好。

这是我们的树(x是节点,其他所有边缘)

   +-------x--+-------+
   |          |       |
 +-x-+     +-+x+-+  +-x-+
 |   |     | | | |  | | |
 x   x     x x x x  x x x

所以,你计算叶子的width s:

   +-------x--+-------+
   |          |       |
 +-x-+     +-+x+-+  +-x-+
 |   |     | | | |  | | |
 1   1     1 1 1 1  1 1 1

然后,自下而上,将width s作为儿童width的总和:

   +-------9--+-------+
   |          |       |
 +-2-+     +-+4+-+  +-3-+
 |   |     | | | |  | | |
 1   1     1 1 1 1  1 1 1

所以,你从根(width 9)开始,然后在第一行中走4.5步。

然后,将“绘图光标”移动到第二行“第0列”(向左)。

第一个孩子有width 2,所以我们向右移动2/2=1网格线并绘制节点并将绘图光标向右移动剩余的1个网格线以完成节点。因此,下一个节点有width 4,这意味着我们右转4/2 = 2个网格线,绘制,继续剩下的2个步骤,依此类推。

等下一行。最后(或中间步骤),连接节点。

此过程确保没有重叠的节点(如果网格线彼此相距足够远),但它可能会导致相当大的树形图可以更有效地利用空间。

为了检测未使用的空间,可以在上述过程之后扫描线,看看是否存在未使用的网格线交叉点,然后可能重新对齐某些节点以填充空间。

答案 1 :(得分:4)

我会尝试Walker算法。关于算法的Here's an academic paper。如果您想要查看代码,请查看NodeLinkTreeLayout中的Prefuse。 Prefuse是开源的,因此只要您遵守许可条款,就不会有任何问题使代码适应您的情况。

答案 2 :(得分:2)

看看Dot。您可以将树转换为点表示,然后以您喜欢的任何格式使用 Graphviz 可视化。例如, Doxygen 使用它来表示程序的结构。

答案 3 :(得分:2)

Graphviz和mfgraph功能强大,但它们适用于一般图形,对树木来说可能有点过分。

尝试在树+布局+算法上使用Google搜索或查看Graphic Javascript Tree with Layout。 后者是旧的,但它使用HTML canvas和javascript,它解释了代码,所以代码和方法都应该是可移植的。

答案 4 :(得分:0)

根据数据的性质,TreeMap可能比tinkertoy代表更合适。

相关问题