通用N-ary树(每个子节点具有两个以上节点的树)Java中的树遍历使用节点的List

时间:2012-10-06 19:55:24

标签: java algorithm generics tree iterator

我一直在尝试在工作中实现Autosys作业计划的树形表示。 由于每个作业(进程)可以有一个或多个依赖作业,我决定使用n-ary树实现,以便我可以映射流。我使用的是java集合。

Q1(已解决):现在的问题是显示功能在无限循环中挂起。 我试图寻找现有的线程但是没有遇到使用迭代器的遍历的例子。

Q2:(OPEN)显示功能以Post Order方式遍历树。我想以级别顺序的方式遍历它,其中节点在级别基础上打印。 Root,然后是第1级上的所有节点,然后是第2级上的所有节点,依此类推。 DFS遍历的链接在下面的链接中作为另一个问题发布。 (大家好,我对同一棵树的关卡顺序遍历有另外一个问题,我已经在下面给出的链接上发布了这个问题。如果你们能提供帮助,那将是一个问题。 Level Order traversal of a generic tree(n-ary tree) in java 让我们为通用树提供更多资源。)

我们能否为那些有n-ary树的新人提供一份资源丰富的帖子,因为我发现很少有基本的例子。

这是我的代码,其中我已经开始使用具有三个子节点的根节点。我打算稍后再扩展它。

一个基本问题。是不是建议在递归中使用迭代器。我尝试在display()中单独定义一个Iterator,但它仍然无效。

当前树结构:

     root(100)
    /      |       \
  90       50       70
  /        \
20 30   200  300

输出是按顺序排列的(不确定这是否意味着DFS)。

20 30 90 200 300 50 70 100

代码

import java.util.*;
import java.io.*;
import java.util.List;

//The node for the n-ary tree


public class NaryTree 
{
//The display function traverses the tree

void display(NaryTreeNode t)
{
    Iterator<NaryTreeNode> IT = t.nary_list.iterator();
    if(!(IT.hasNext()))   //If the node does not  have any children, enter.
    {
    //    System.out.println("No more childs of this node");
        System.out.print( t.data + " ");
        return;
    }

    while(IT.hasNext()){
        display(IT.next()) ;            //Recursive Call
    }

   System.out.print(t.data + " ");
}

public static void main(String args[]){

    NaryTree t1 = new NaryTree();

    NaryTreeNode root = new NaryTreeNode();

    root.data = 100;

    NaryTreeNode lev_11 = new NaryTreeNode();   lev_11.data=90;
    NaryTreeNode lev_12 = new NaryTreeNode();   lev_12.data=50;
    NaryTreeNode lev_13 = new NaryTreeNode();   lev_13.data=70;
    NaryTreeNode lev_21 = new NaryTreeNode();   lev_21.data=20;
    NaryTreeNode lev_22 = new NaryTreeNode();   lev_22.data=30;
    NaryTreeNode lev_23 = new NaryTreeNode();   lev_23.data=200;
    NaryTreeNode lev_24 = new NaryTreeNode();   lev_24.data=300;

    //Add all the nodes to a list.



    List<NaryTreeNode> temp2 = new ArrayList<NaryTreeNode>();  //Level two first branch
    temp2.add(lev_21);
    temp2.add(lev_22);

    List<NaryTreeNode> temp3 = new ArrayList<NaryTreeNode>();  //level two second branch
    temp3.add(lev_23);
    temp3.add(lev_24);

    List<NaryTreeNode> temp = new ArrayList<NaryTreeNode>();  //level one
    temp.add(lev_11);
    temp.add(lev_12);
    temp.add(lev_13);

    lev_11.nary_list.addAll(temp2);
    lev_12.nary_list.addAll(temp3);
    //Add Temp to root  to form a leaf of the root

    root.nary_list.addAll(temp);
    //Call the display function.
    t1.display(root);

} }

3 个答案:

答案 0 :(得分:3)

nary_list.iterator()

每次都创建一个新的迭代器。因此,如果列表中包含任何内容,则这将是一个无限循环;它每次运行时都会创建一个新的迭代器,并且始终包含元素:

while(t.nary_list.iterator().hasNext()){

如果您想直接使用迭代器,可以这样做:

Iterator<NaryTreeNode> iterator = t.nary_list.iterator();
while (iterator.hasNext()) {

但是,你也可以在Java中使用for each循环来减少这个问题:

for (NaryTreeNode node : t.nary_list) 

修改

我还会按此顺序编写显示函数,以便在耗尽迭代器后打印当前节点的值,而不必询问!hasNext()

// Display all of my children
for (NaryTreeNode node : t.nary_list) {
    display(node);
}

// Display myself
System.out.println("Value is: " + t.data);

答案 1 :(得分:2)

在我看来,每次循环都会创建一个新的迭代器,因此每个都设置为列表的开头。我稍后会尝试添加规范参考。尝试:

    Iterator<NsryTreeNode> i = t.nary_list.iterator();
    while(i.hasNext()){
        display(t.nary_list.iterator().next()) ;            //Recursive Call
    }

您可能需要查看http://docs.oracle.com/javase/tutorial/collections/interfaces/list.html。您可能会发现ListIterator具有值。

答案 2 :(得分:2)

我不知道Java能够理解该循环中可能发生的事情,但它看起来很可疑;我读到的方式是,每次循环都会创建一个新的迭代器。

我还建议您考虑使用first-child / next-sibling而不是在每个节点中放置列表。在这个系统中,每个节点引用(最多)两个其他节点:它的第一个子节点(如果它有任何子节点)和它的下一个兄弟节点(除非它是它的父节点的最后一个兄弟节点)。然后,您可以通过兄弟列表遍历兄弟列表以枚举子节点,并且您不会在每个节点中获得可变长度数组的所有开销。