简体   繁体   中英

Generic N-ary Tree (Tree with more than two node per child) Tree Traversal in Java using List for nodes

I have been trying to implement a tree representation of Autosys job schedules at work. As each job(process) can have one or or more dependent job on them, i decided to go with a n-ary tree implementation so that i can map the flow. I an using java collections for the same.

Q1(Solved): The problem for now is that the display functions is getting hung up in a infinite loop. I tried looking for existing threads but could not come across examples for traversals using iterators.

Q2:(OPEN)The display function traverse the tree in a Post order manner. I would like to traverse it in a level order manner wherein the nodes get printed on level basis. Root, then all nodes on level one and then all nodes on level 2 and so on. The link for the DFS traversal is posted as another question at the link below. (Hi guys, I have another question for the level order traversal of the same tree, I have posted the question on the link given below. Would be gald if you guys could help. Level Order traversal of a generic tree(n-ary tree) in java Let us make this more resourceful for generic trees.)

Can we make this a resourceful post for people new with n-ary trees because I found very few elementary examples out there.

Here is my code where i have started with a root node with three children. I plan to expand this later.

One elementary question. Is using iterator in recursion not advised. I tried definig an Iterator separate in display() but it still didn't work.

Current Tree Structure:

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

The output is in post order(not sure if that means DFS).

20 30 90 200 300 50 70 100

Code

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);

} }

nary_list.iterator()

Creates a new iterator every time. So if a list has anything inside it, this will be an infinite loop; it creates a new iterator every time it is run, and always has the element in it:

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

If you want to work with iterators directly, you could do this:

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

However, you can also use the for each loop in Java to make this less wordy:

for (NaryTreeNode node : t.nary_list) 

EDIT

I would also write the display function in this order, so that you print the value of the current node after exhausting the iterator, rather than having to ask !hasNext() :

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

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

It appears to me you are creating a fresh iterator each time through the loop, so each is set to the beginning of the list. I'll try to add the spec reference in a moment. Try:

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

You may want to look at http://docs.oracle.com/javase/tutorial/collections/interfaces/list.html . You may find the ListIterator to have value.

I don't know enough Java to understand what might be going on in that loop but it looks suspicious to me; the way I read that, you're creating a new iterator every time through the loop.

I would also suggest you consider the option of using first-child/next-sibling instead of putting a list in every node. In this system, every node references (at most) two other nodes: its first child (if it has any children) and its next sibling (unless it is the last sibling of its parent). You can then walk the sibling list through the sibling lists to enumerate children nodes, and you don't end up with all the overhead of a variable length array in every node.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM