获取树结构中的所有可能路径

时间:2016-11-16 08:07:10

标签: java recursion tree ontology wordnet

我需要在树中循环才能获得所有可能的路径,我的代码中的问题只是第一条路径!

例如: enter image description here

在图中,有2条路径可以处理:1-2-3-4-5-6和1-2-3-7-8,但我无法同时获得这两条路径,我刚刚检索过1-2-3-4-5-6!

我的代码:

主要:

for (String key : synset.keySet()) { // looping in a hash of Concept and it's ID
        System.out.println("\nConcept: " + key + " " + synset.get(key));
        List<Concept> ancts = myOntology.getConceptAncestors(myOntology.getConceptFromConceptID(synset.get(key))); // this function retreives the root of any node.

        for (int i = 0; i < ancts.size(); i++) {
            System.out.print(ancts.get(i).getConceptId() + " # ");
            System.out.print(getChilds(ancts.get(i).getConceptId()) + " -> "); // here, the recursive function is needed to navigate into childs.. 
        }
        System.out.println("");
    }

记录。功能:

public static String getChilds(String conId)
{
    List<Concept> childs = myOntology.getDirectChildren(myOntology.getConceptFromConceptID(conId)); // get all childs of a node
    if(childs.size() > 0)
    {
        for (int i = 0; i < childs.size(); i++) {
            System.out.print( childs.size() + " ~ " + childs.get(i).getConceptId() + " -> ");
            return getChilds(childs.get(i).getConceptId());
        }
    }
    else
        return "NULL";
    return "final";
}

3 个答案:

答案 0 :(得分:3)

getChilds()中的此代码段可能存在问题:

for (int i = 0; i < childs.size(); i++) {
        System.out.print( childs.size() + " ~ " + childs.get(i).getConceptId()    + " -> ");
        return getChilds(childs.get(i).getConceptId());
}

for loop无法发挥作用,它总是return getChilds(childs.get(0).getConceptId()); 也许这不是你想要的。

答案 1 :(得分:0)

一个简单的方法。
您只需要一个树遍历和一点自定义代码。

  • 有一个名为tempPath的列表。你可以将它作为一个参数或全局变量。
  • 进行树遍历(例如,按顺序)。每当你在一个节点时,最后将它添加到tempPath列表中,当你完成这个节点时,从tempPath的末尾删除节点。
  • 每当遇到一个叶子时,你都有一个从root到leaf的完整路径,它包含在tempPath中。您可以将此列表值打印或复制到另一个数据结构中。

答案 2 :(得分:0)

我没有看到足够的代码来使用您定义的类。所以我去写自己的工作解决方案。

在下面的代码中,使用递归来解决问题:

public class TreeNode {
    private String id;
    private TreeNode parent;
    private List<TreeNode> children;

    public TreeNode(String id) {
        this.id = id;
        this.children = new LinkedList<>();
    }

    public void addChild(TreeNode child) {
        this.children.add(child);
        child.setParent(this);
    }

    public List<TreeNode> getChildren() {
        return Collections.unmodifiableList(this.children);
    }

    private void setParent(TreeNode parent) {
        this.parent = parent;
    }

    public TreeNode getParent() {
        return this.parent;
    }

    public String getId() {
        return this.id;
    }
}

public class TreePaths {
    private static List<List<TreeNode>> getPaths0(TreeNode pos) {
        List<List<TreeNode>> retLists = new ArrayList<>();

        if(pos.getChildren().size() == 0) {
            List<TreeNode> leafList = new LinkedList<>();
            leafList.add(pos);
            retLists.add(leafList);
        } else {
            for (TreeNode node : pos.getChildren()) {
                List<List<TreeNode>> nodeLists = getPaths0(node);
                for (List<TreeNode> nodeList : nodeLists) {
                    nodeList.add(0, pos);
                    retLists.add(nodeList);
                }
            }
        }

        return retLists;
    }

    public static List<List<TreeNode>> getPaths(TreeNode head) {
        if(head == null) {
            return new ArrayList<>();
        } else {
            return getPaths0(head);
        }
    }
}

要使用上面的代码,必须使用TreeNode类构造树。首先创建一个头TreeNode,然后根据需要添加子节点。然后将头部提交给TreePaths getPaths静态函数。

getPaths检查null后,将调用内部getPaths0函数。在这里,我们通过尝试尽快到达所有叶节点来遵循深度优先方法。找到叶节点后,将创建仅包含此叶节点的List,并在列表集合中返回。然后将此叶节点的父节点添加到列表的开头,该列表将再次放入列表集合中。这将发生在父母的所有孩子身上。

最后,所有可能的路径都将以单一结构结束。可以按如下方式测试此功能:

public class TreePathsTest {
    TreeNode[] nodes = new TreeNode[10];

    @Before
    public void init() {
        int count = 0;
        for(TreeNode child : nodes) {
            nodes[count] = new TreeNode(String.valueOf(count));
            count++;
        }
    }

    /*
     * 0 - 1 - 3
     *       - 4
     *   - 2 - 5
     *       - 6
     *       - 7 - 8
     *           - 9
     */
    private void constructBasicTree() {
        nodes[0].addChild(nodes[1]);
        nodes[0].addChild(nodes[2]);
        nodes[1].addChild(nodes[3]);
        nodes[1].addChild(nodes[4]);
        nodes[2].addChild(nodes[5]);
        nodes[2].addChild(nodes[6]);
        nodes[2].addChild(nodes[7]);
        nodes[7].addChild(nodes[8]);
        nodes[7].addChild(nodes[9]);
    }

    @Test
    public void testPaths() {
        constructBasicTree();
        List<List<TreeNode>> lists = TreePaths.getPaths(nodes[0]);
        for(List<TreeNode> list : lists) {
            for(int count = 0; count < list.size(); count++) {
                System.out.print(list.get(count).getId());
                if(count != list.size() - 1) {
                    System.out.print("-");
                }
            }
            System.out.println();
        }
    }
}

这将打印出来:

0-1-3
0-1-4
0-2-5
0-2-6
0-2-7-8
0-2-7-9

注意:上述内容足以进行手动测试,但应修改测试功能,以便对正确的自动化单元测试进行适当的断言。

相关问题