4
votes

I would like to display the tree structure level by level. My current code does a BFS or Level Order Traversal but I cannot get the output to display the tree structure like a tree See current output and Expected output.

My idea was to use some kind of count to iterate over elements from the same level in the queue.

How can I do so.

Original Code without this function can be found in the link below in case someone needs the entire implementation else just look at the displayBFS function below.

Level Order traversal of a generic tree(n-ary tree) in java

Thanks!

   void displayBFS(NaryTreeNode n)
   {
      Queue<NaryTreeNode> q  = new LinkedList<NaryTreeNode>();
      System.out.println(n.data);

       while(n!=null)
     {   
         for(NaryTreeNode x:n.nary_list)
         {
             q.add(x);
             System.out.print(x.data + " ");
         }
         n=q.poll();
         System.out.println();
      } 
  }

Current Tree Structure for reference:

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


    Current Output:
        100
        90 50 70
        20 30
        200 300

    Expected Output
        100
        90 50 70
        20 30 200 300    

Also, I had posted a logic issue with the same function earlier, as that was answered and the current question realtes to a different problem, I posted a new question, is this approach okay or should I make edits to the earlier question and not open a new one?

5

5 Answers

2
votes

only need to keep track of current level and next level.

static void displayBFS(NaryTreeNode root) {
    int curlevel = 1;
    int nextlevel = 0;

    LinkedList<NaryTreeNode> queue = new LinkedList<NaryTreeNode>();
    queue.add(root);

    while(!queue.isEmpty()) { 
        NaryTreeNode node = queue.remove(0);

        if (curlevel == 0) {
            System.out.println();
            curlevel = nextlevel;
            nextlevel = 0;
        }

        for(NaryTreeNode n : node.nary_list) {
            queue.addLast(n);
            nextlevel++;
        }

        curlevel--;
        System.out.print(node.data + " ");
    } 
}

when you switch levels, swap nextlevel for currentlevel and reset nextlevel. i prefer the simplicity of this over keeping a whole separate queue.

i had this question for a microsoft interview last week... it didn't go so well for me over the phone. good on you for studying it.

2
votes

The simplest solution I know of to this problem is to use a sentinel. The queue is initialized with the root node followed by the sentinel, and then you loop through the queue:

  1. remove the front element
  2. if it is the sentinel:
    • we're at the end of a level, so we can end the output line
    • if the queue is not empty, push the sentinel back onto the queue at the end.
  3. if it is not the sentinel:
    • print it out
    • push all its children onto the queue.

I don't do Java, but I have some C++ code for depth-aware BFS, which I stripped down to do this printing task:

void show_tree_by_levels(std::ostream& os, Node* tree) {
  Node* sentinel = new Node;
  std::deque<Node*> queue{tree, sentinel};
  while (true) {
    Node* here = queue.front();
    queue.pop_front();
    if (here == sentinel) {
      os << std::endl;
      if (queue.empty())
        break;
      else
        queue.push_back(sentinel);
    } else {
      for (Node* child = here->child; child; child = child->sibling)
        queue.push_back(child);
      os << here->value << ' ';
    }
  }
}

Note that I prefer to use a two-pointer solution (first_child/next_sibling), because it usually works out to be simpler than embedded lists. YMMV.

1
votes

Use another queue to indicate depth. The below code is not tested, but it should give you the idea (the sep variable is introduced to avoid trailing white-spaces):

void displayBFS(NaryTreeNode n) {
  Queue<NaryTreeNode> q  = new LinkedList<NaryTreeNode>();
  Queue<Integer> depth  = new LinkedList<Integer>();
  q.add(n);
  depth.add(0);

  String sep = "";
  int oldDepth = 0

  while(!q.isEmpty()) {
    NaryTreeNode currN = q.poll();
    int currDepth = depth.poll();
    if (currDepth > oldDepth) {
      System.out.println();
      oldDepth = currDepth;
      sep = "";
    }
    System.out.print(sep + currN.data);
    sep = " ";

    for(NaryTreeNode x : currN.nary_list) {
      q.add(x);
      depth.add(currDepth + 1);
    }
  }
}

For my taste this approach is more self-explanatory compared to other ways one could do it.

1
votes

I think we need three more variables. numInCurrentLevel for keeping track of the number of elements in current level, indexInCurrentLevel for doing the count when traversal in current level and numInNextLevel for keeping track of the number of elements in next level. The code is below:

static void displayBFS(NaryTreeNode root) {

    Queue<NaryTreeNode> q  = new LinkedList<NaryTreeNode>();;
    q.add(root);
    int numInCurrentLevel = 1;
    int numInNextLevel = 0;
    int indexInCurrentLevel=0;

    while(!q.isEmpty()) { 
        NaryTreeNode node = q.poll();
        System.out.print(node.data + " ");
        indexInCurrentLevel++;

        for(NaryTreeNode n : node.nary_list) {
            q.add(n);
            numInNextLevel++;
        }

        //finish traversal in current level
        if(indexInCurrentLevel==numInCurrentLevel) {
            System.out.println();
            numInCurrentLevel=numInNextLevel;
            numInNextLevel=0;           
            indexInCurrentLevel=0;
        }
  } 
}

Hope it helps, I am not so familiar with java programming.

0
votes
def printLevelWiseTree(tree):
q= queue.Queue()
if tree == None:
    return None
q.put(tree)
while (not(q.empty())):
    c = q.get()
    print(c.data,end=":")
    for i in range(len(c.children)):
        if i != len(c.children)-1:
            print(c.children[i].data,end=",")
        else:
            print(c.children[i].data,end="")
        q.put(c.children[i])
    print()