用于节点搜索的图遍历

时间:2012-06-17 10:11:48

标签: graph tree graph-algorithm tree-traversal

在下面给出的图中,递归遍历子部件。每个孩子必须报告其直系亲属。问题是孩子[3]必须在同一行同时报告其直接父母(即孩子[2]和孩子[4])。

traverse(Node node)
{
    if(node == null)
        return;

    for(Node child : node.getChilds()) {
        traverse(child);
    }
}

Parent 
|---child[1]
|       child[2]
|           child[3]
|---child[4]
        child[3]

现在我一次遍历一个节点,产生的输出是 -

Node      Immediate Parent
--------------------------
child[2]  child[1]
child[3]  child[2]
child[3]  child[4]

预期输出为 -

Node      Immediate Parent
--------------------------
child[2]  child[1]
child[3]  child[2], child[4]

搜索节点并为图表生成预期输出的最佳方法是什么?任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:8)

如果您有(或可以添加)链接回父母,您可以在第一次遇到节点时列出所有父母,然后在重复访问时跳过它。您有多个选项可以跟踪节点是否已被访问过:

  1. 维护一组受访节点并检查当前节点是否在该集合中。如果没有,处理它并将其添加到集合中;否则跳过。

    优势:一般方法

    缺点:如果图表很大,可能需要大量内存来维护集合

  2. 向节点添加isVisited成员值(默认设置为false)并在遇到节点时进行检查:如果值为false,则处理节点并将isVisited设为true;否则跳过。

    优势:减少额外内存

    缺点:侵入性,特定于任务,额外的变量即使在不需要时也存在,对于需要多个这样的“已经处理过的”决策的任务而言不能很好地扩展同时

  3. 如果父链接选项不可用,您可以在额外地图中维护子到父关系:您在处理节点时从子映射到父集合。完成初始处理(构建地图)后,迭代地图并列出每个节点及其父节点。

    直接父链接上的优点是在构建/修改图表时没有额外的维护(除非你想让映射保持最新)

    缺点是每次想要在对图形结构进行一系列修改后处理图形时必须重新构建地图(除非 - 请参阅注释adventage)

    注意:如果图中有定向(父对子)圆,则遍历所有子项遍历一般图可能会导致无限循环。我想你的问题并非如此,只是为了涵盖所有基础:你可以在处理图形时维护一组“访问过的”节点。可用选项的讨论与第一部分(“链接回父母”)部分的讨论相同