【问题标题】:Traversing a tree recursively in depth first problems递归遍历树的深度优先问题
【发布时间】:2012-03-15 16:53:49
【问题描述】:

我正在尝试使用 ANTLR 树命令和递归遍历树。我目前拥有的代码是:

public void traverseTree(Tree tree){
        int counter = 0;
        System.out.println(tree.toString());
        if (tree.getChildCount() > 0 && tree.getChild(0) != null){
            System.out.println(tree.toString() + counter++);
            tree = tree.getChild(0);
            traverseTree(tree);

        }
        while (tree.getParent().getChild(tree.getChildIndex() + 1) != null){
            System.out.println(tree.toString() + counter++);
            tree = tree.getParent().getChild(tree.getChildIndex() + 1);
            traverseTree(tree);

        }
    }

但是,好吧,它不起作用。我在树中获得了很多条目,但没有明显的顺序。谁能看出我哪里出错了?

谢谢。

编辑:

我在下面发表的评论应该是在这里开始的:

抱歉,我应该删除打印语句,他们只是在那里尝试调试它。我遇到的问题是它应该只搜索它开始的节点以及该节点的任何兄弟节点,它不应该上升一个级别,但它确实会打印所有内容。 (我将把它编辑到主目录中,它本来应该在那里,抱歉)。

我设法让代码最终像这样工作:

public void traverseTree(Tree tree){
        System.out.println(tree);
        if (tree.getChild(0) != null){
            traverseTree(tree.getChild(0));
        }
        if(tree.getParent().getChildCount() > 1){
            if(tree.getParent().getChild(tree.getChildIndex() + 1) != null)
            traverseTree(tree.getParent().getChild(tree.getChildIndex() + 1));
        }
    }

【问题讨论】:

  • “深度优先”...你的意思是水平顺序吗?反水平顺序?我很困惑.. 其他可能性是预购、订购、后购

标签: java recursion tree antlr


【解决方案1】:

确保它永远不会上升的最简单方法是确保您永远不会致电getParent()。如果你不知道有上层,你就不能去那里。

public void traverseTree(Tree tree) {

    // print, increment counter, whatever
    System.out.println(tree.toString());

    // traverse children
    int childCount = tree.getChildCount();
    if (childCount == 0) {
        // leaf node, we're done
    } else {
        for (int i = 0; i < childCount; i++) {
            Tree child = tree.getChild(i);
            traverseTree(child);
        }
    }
}

递归的全部意义在于您不需要返回。当这一层的traverseTree() 结束时,上一层的循环将继续到下一层。

(请注意,if 实际上并不是必需的,除非您想在到达叶节点时做一些特别的事情。我只是把它放在那里,这样评论就会清楚发生了什么。从概念上讲,它总是递归是一个好主意,首先要弄清楚你如何知道何时停止递归。)

【讨论】:

  • 但就是这样,我从不使用 getParent() 除非我正在做 getParent.getChild(getChildIndex() + 1) ,这只是将它移动到下一个兄弟姐妹(没有似乎是另一种方法)。
  • 你不需要移动到下一个兄弟姐妹。父级的循环负责这一点。
  • (当然,你实际上必须有一个循环。我想没有循环也可以做到,但我不知道你为什么想要。)
  • 好的,经过仔细检查,我知道发生了什么。你循环你的兄弟姐妹而不是循环你的孩子。由于您必须上去父级获取兄弟姐妹,因此无法(没有额外信息)阻止遍历一直爬到树的根部。
  • 我会将您的答案标记为正确,因为您帮助我解决了一些错误。导致真正麻烦的事情实际上是在代码的前面一点。如果有人遇到类似问题,我会发布工作代码。谢谢!
【解决方案2】:

您似乎多次打印出相同的节点。如果你只是想在下行时打印出节点,

   1
 2   3
4 5   6

Depth first - 1 2 4 5 3 6
Breadth first - 1 2 3 4 5 6

//For depth first
public void traverseTree(Tree tree){        
    System.out.println(tree.toString());
    for (int x = 0; x < tree.getChildCount(); x++)
        traverseTree(tree.getChild(x));
}

要切换到 4 5 6 2 3 1,只需将 println 移到 for 循环之后。

【讨论】:

  • 对不起,我应该删除打印语句,他们只是在那里尝试调试它。我遇到的问题是它应该只搜索它开始的节点和该节点的任何兄弟节点,它不应该上升一个级别,但它确实会打印所有内容。 (我将把它编辑到主目录中,它应该一开始就在那里,抱歉)。
  • @Incredidave Thomas 的解决方案(几乎)适用于您提供的任何节点(它应该有空退出语句)。如果你想从一个孩子开始,只需传递它而不是根。您确实需要更具体地了解您尝试访问每个节点的方式、您打算在那里做什么以及以什么顺序。
  • 我假设孩子们是非空的,所以它会因为 getChildCount() 为 0 而终止。无论如何,它不能回答实际问题。
【解决方案3】:

试试这个:

int counter = 0;
public void traverseTree(Tree tree) {

    for (int i=0; i<tree.getChildCount(); i++) {
        Tree child = tree.getChild(i);
        System.out.println(tree.toString() + counter++);
        traverseTree(tree);
    }
}

【讨论】:

    猜你喜欢
    • 2012-11-20
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多