从第3页的演示文稿:Graphs and Trees,可以直观地了解Reigngold-Tilford过程中发生的事情;它还提前对这个算法进行了模糊的总结:"...starts with bottom-up pass of the tree;
[finishes with] Top-down pass for assignment of final positions..."
我可以通过递归方式实现两个方向传递,我知道Y值与每个节点的生成级别相对应,但我是仍然失去了如何解决X坐标。
我确实遇到过这个项目:A Graph Tree Drawing Control for WPF但是有很多代码我很难找到应该是一个简单的2-3方法来定义X值。 (也没有WPF的经验)
我几天来一直在寻找并尝试如何做到这一点,所以非常感谢您的帮助!
答案 0 :(得分:21)
我发现jwpat7's answer中列出的文章非常有用,虽然我花了一些时间才弄清楚这个算法所需的确切逻辑,所以我写了own blog post来简化解释。
以下是确定X节点位置的明文逻辑:
从树的post-order traversal开始
如果每个节点是一个集合中的第一个,则为每个节点分配一个初始X值,如果不是,则为previousSibling + 1
。
如果某个节点有子节点,请找到所需的X值,使其居中于子节点上。
如果节点是最左侧的节点,请将其X设置为该值
如果节点不是最左边的节点,请将节点上的Mod
属性设置为(X - centeredX)
,以便移动所有子节点,使它们在此节点下居中。树的最后一次遍历将使用此Mod
属性来确定每个节点的最终X值。
确定此节点的任何子节点是否与此节点左侧的兄弟节点子节点重叠。基本上对于每个Y,从两个节点获取最大和最小的X,并进行比较。
如果发生任何碰撞,请将节点移动一段时间。移动子树只需要添加节点的X
和Mod
属性。
如果节点被移动,也会在两个重叠的子树之间移动任何节点,使它们等间隔
检查以确保在计算最终X时,没有负X值。如果找到任何内容,请将最大的一个添加到根节点的X
和Mod
站点以将整个树移到
使用预先遍历遍历对树进行第二次遍历,并将节点父节点中每个Mod
值的总和添加到{{1} X
属性
上面树的最终X值如下所示:
我在my blog post中有一些更多的细节和一些示例代码,但是在这里包含所有内容的时间太长了,我想专注于算法的逻辑而不是代码细节。
答案 1 :(得分:2)
有一些文章包括代码,在billmill.org的python中和1991年2月1日的page 2中的C Dr. Dobb's Journal article。你已经要求“简单的2-3种方法”(也许意味着食谱方法),但在它们的一般性中很好地绘制树是NP完全问题(参见Supowit,KJ和EM Reingold,“很好地绘制树木的复杂性”,Acta Informatica 18,4,1983年1月,377-392,DDJ文章中的参考文献4)。 Reingold-Tilford方法在线性时间内或多或少地绘制二叉树,而Buchheim的变化在线性时间内或多或少地绘制了n-ary树。然而,billmill的文章指出(在说明原则6之后不久),“到目前为止我们已经在本文中查看了一个简单的算法,我们发现它不够......”因此更简单的方法工作的可能性好的很小。