【发布时间】:2010-06-17 22:41:23
【问题描述】:
这是一棵非常普通的二叉树,只是其中一个节点可能为空。
我想找一种方式,横向输出(即根节点在左边,向右展开)。
我有一些垂直扩展树的经验(根节点在顶部,向下扩展),但在这种情况下我不确定从哪里开始。
最好遵循以下几条规则:
- 如果一个节点只有一个子节点,则可以将其作为冗余节点跳过(始终显示没有子节点的“结束节点”)
- 相同深度的所有节点必须垂直对齐;所有节点都必须位于所有较浅节点的右侧和所有较深节点的左侧。
- 节点具有包含其深度的字符串表示形式。
- 每个“端节点”都有自己独特的线路;也就是说,行数就是树中的结束节点的数量,当一个结束节点在一行上时,在该结束节点之后的那一行上可能没有其他内容。
- 作为最后一条规则的结果,根节点可能在左上角或左下角更好;首选左上角。
例如,这是一棵有效的树,有六个末端节点(节点由名称及其深度表示):编辑:请参阅问题底部的替代方案,更容易呈现 [a0]-----------[b3]------[c5]------[d8] \ \ \----------[e9] \ \----[f5] \-[g1]--------[h4]------[i6] \ \--------------------[j10] \-[k3]
代表垂直的显式二叉树:
0个 / \ 1 克 * / \ \ 2 * * * / \ \ 3 k * b // \ 4 小时 * * / \ \ \ 5 * * f c / \ / \ 6 * 我 * * // \ 7 * * * // \ 8 * * 天 // 9 * e / 10 焦(为紧凑而折叠的分支;* 代表冗余的单子节点;请注意,* 是实际节点,每个节点存储一个子节点,只是此处省略了名称以进行演示清酒)
(另外,澄清一下,我想生成第一棵水平树;而不是这棵垂直树)
我说与语言无关是因为我只是在寻找一种算法;我说 ruby 是因为我最终还是要在 ruby 中实现它。
假设每个Node数据结构只存储了它的id、一个左节点和一个右节点。
一个主 Tree 类跟踪所有节点并有足够的算法来查找:
- 节点的第 n 个祖先
- 节点的第 n 个后代
- 一个节点的所有端节点后代,及其计数
- 节点的生成
- 两个给定节点的最低共同祖先
我已经知道:
- 端节点数
有人知道我可以从哪里开始吗?我应该采用递归方法吗?迭代? 一些伪代码也会很酷,非常感谢 =)
进展
根据 walkytalky 的建议,我决定看看将每个“相关”或重要节点映射到网格会是什么样子,其中列是深度,行可以由它们的末端节点识别。以下是发生的情况(跳过第 7 列,因为深度 7 中没有重要节点):
深度:0 1 2 3 4 5 6 8 9 10 A B C D e F 我 j ķ使用广度优先或深度优先搜索生成此网格应该很容易。也许最简单的方法是简单地保留一个二维数组并将找到的每个重要节点放入其中,为每个“第二个孩子”插入一行。
现在,了解这些事实:
- 一行中的最后一个节点必须是结束节点
- 子节点始终位于其父节点的右侧,并且在同一行或更低的位置。
- 所有非端节点必须恰好有两个子节点
- 因此,所有非结束节点的子节点其列右侧的第一个,第一个子节点在同一行,第二个子节点 n 它们下面的行,其中 n 是其右侧的节点数。
我们可以看到,给定任何有效的网格,可以说,有一种明确的方式来“连接点”;代表的是一棵明确的树。
现在,“连接点”不再是一个二叉树结构问题……它只是一个装饰问题。我们只需要构建一个算法来将正确的- 和\ 正确放置在它们可以去的地方,也许只遵循简单的网格/字典规则,而不是二叉树-结构规则。
基本上,这意味着渲染树的问题现在是渲染网格的简单得多的问题,带有花哨的装饰。
谁能提出任何制定这些规则的方法?或者完全不同的方法?
编辑
我构思了一个更简单的最终渲染:
--d0----d1----d3----d4----d5----d6----d8----d9----d10-- => 指导线 (未渲染) [a0]-------[b3]--------[c5]-------[d8] | | \---------------[e9] | \---------[f5] \---[g1 ]-------[h4 ]-------[i6 ] | \---------------------------------------[j10] \---[k3] --d0----d1----d3----d4----d5----d6----d8----d9----d10-- => 指导线 (未渲染)尝试创建这个可能会更容易,而不是我之前发布的那个。一方面,它保留了一个漂亮的网格形状,你不必用对角线变化无常。这些行都沿着清晰可见的列线映射。不幸的是,它远没有第一个漂亮。
【问题讨论】:
-
你的数据结构是什么样的?
-
这不是您真正要的,但您可以渲染到dot,然后告诉graphvis 为您制作图像。
-
@user257493 - 我会说数据结构无关紧要,不是自命不凡或特别无用,而是因为我将直接提取原始数据,并将其解析为最适合这项任务的任何数据结构。
-
关于您的编辑:举个简单的例子,将每行 n 偏移 n 个前导空格,用斜杠替换所有管道。这是一个与偏移量之间的微不足道的转换。
-
@Jimmy - 谢谢!我想我会使用它;现在似乎更容易解决首先构建直线示例,然后将其转换为弯曲示例的问题?
标签: ruby algorithm language-agnostic text binary-tree