递归计算树中的特殊节点

时间:2017-10-17 15:58:04

标签: java algorithm recursion tree traversal

我构建了一个由节点组成的树,每个节点都有一个属性和一个后继列表。我试图实现一个递归函数,它开始在给定节点遍历树(在这个例子中是节点"方法")。该函数应计算具有给定属性的嵌套节点的数量。最后,我想返回一个分支中找到的最高编号。 说到给定的例子,我想找到具有属性" Loop"的最大嵌套节点数量。这将是3(相应的分支标记为橙色)。

实施例: enter image description here 目前,我的方法如下:

private static int getLNDforMethod(DirectedNodeInterface curNode, int currentLND) {

    NodeIterator successors = curNode.getSuccessors();
    while(successors.hasNext())
    {
        successors.next();
        DirectedNodeInterface curSuc = (DirectedNodeInterface) successors.getNode();

        // isLoop returns true if the given node is a loop
        if(isLoop(curSuc))
        {
            ++currentLND;
        }

        currentLND = getLNDforMethod(curSuc, currentLND);
    }

    return currentLND;
}

这种方法的问题在于它计算给定树中的所有循环,而不是仅仅返回嵌套分支的最大数量。因此,不是返回3(这将是我想要的),而是返回给定示例的7,其等于"循环"的总数。在整棵树上。

显然,我在考虑递归方法时遇到了一些麻烦。有人能帮助我吗?

3 个答案:

答案 0 :(得分:5)

考虑递归算法的一个非常好的策略是假设您已经实现了算法。在您的情况下,这意味着假设您已经有一个函数可以找到单个路径的max。您的实现归结为为每个孩子调用函数(记住,我们正在假设它' s已经实现了),在它们中选择最大值,然后返回最大值,或者如果当前节点满足条件则返回max加1。

查找单个路径的最大计数的算法如下:

  • 将方法的返回值max设置为0
  • 如果所需属性不存在,则将当前节点添加的值own设置为0;如果当前节点中存在该属性,则设置为1
  • 为每个孩子致电getLNDforMethod,然后获取childMax
  • max设置为maxown+childMax
  • 的最大值
  • 返回max

这在Java代码中更容易表达:

private static int getLNDforMethod(DirectedNodeInterface curNode) {
    int max = 0;
    int own = isLoop(curNode) ? 1 : 0;
    NodeIterator successors = curNode.getSuccessors();
    while(successors.hasNext()) {
        successors.next();
        DirectedNodeInterface curSuc = (DirectedNodeInterface) successors.getNode();
        max = Math.max(max, own + getLNDforMethod(curSuc));
    }
    return max;
}

答案 1 :(得分:3)

private static int getLNDforMethod(DirectedNodeInterface curNode) {

    int maxChild = 0;
    NodeIterator successors = curNode.getSuccessors();
    while(successors.hasNext())
    {
        successors.next();
        DirectedNodeInterface curSuc = (DirectedNodeInterface) successors.getNode();
        maxChild = Math.max(maxChild, getLNDforMethod(curSuc));
    }

    return maxChild + (isLoop(curNode) ? 1 : 0);
}

答案 2 :(得分:2)

您的问题是您正在进行广度优先搜索,而无需考虑您自己的问题陈述。你想要的是,任何分支中LOOP的最大出现次数,但你正在做的是计算整个树中LOOP的所有出现次数。您可以通过将广度优先搜索转换为深度优先搜索或仅返回子递归调用的最大结果来解决此问题。

private static int GetLNDForMethod(DirectedNodeInterface curNode) {
    NodeIterator successors = curNode.getSuccessors();
    unsigned int numLnds = 0;
    while (successors.hasNext()) {
        successors.next();
        DirectedNodeInterface curSuc = (DirectedNodeInterface) successors.getNode();

        unsigned int curLnds = GetLNDForMethod(curSuc);
        if (isLoop(curSuc))
            curLnds++;
        if (numLnds < curLnds)
            numLnds = curLnds;
    }

    return numLnds;
}

我在这里所做的并不是对你的代码的大修改,我只是插入另一个变量并检查它是否大于当前值并设置第一个如果是。

请注意,由于您(和我)仅考虑后继者而不检查当前节点,因此如果根节点为LOOP

,则此结果将低于实际结果的结果