Data Structures, Algorithms, & Applications in Java
Chapter 12, Exercise 29

We perform a level-order traversal. To differentiate among nodes at different levels, we use a unique pointer which serves as an end of level marker. This pointer is added to the level order queue following the last node at each level. As nodes are removed from the queue, a counter is incremented until the end of level marker is removed. This strategy enables us to determine the number of nodes in a level. The code is given below. A test program and output are given in the files BinaryTreeMaxLevel.*.
public class BinaryTreeMaxLevel
{
   /** @return level with max umber of nodes */
   public static int maxLevel(BinaryTreeNode t)
   {
      if (t == null)
         // tree is empty
         return 0;

      // maxLevel is current level with max nodes
      // maxNodes is number of nodes on level maxLevel
      int maxLevel = 0;
      int maxNodes = 0;
      
      // create a unique pointer to use an end of level marker in queue
      BinaryTreeNode endOfLevel = new BinaryTreeNode();
   
      // put t and endOfLevel marker on queue q
      ArrayQueue q = new ArrayQueue();
      q.put(t);
      q.put(endOfLevel);

      // do a level order traversal
      int currentLevel = 1;    // level of nodes being examined
      int numOfNodes = 0;      // number of nodes seen of currentLevel
      while (true) 
      {
         BinaryTreeNode p = (BinaryTreeNode) q.remove();
         if (p == endOfLevel)
         {
            // see if currentLevel has more nodes than MaxLevel
            if (numOfNodes > maxNodes)
            {// found a level with more nodes
               maxNodes = numOfNodes;
                maxLevel = currentLevel;
            }
            else
               if (numOfNodes == 0)
                  // empty level, no more nodes
                  return maxLevel;

            // set currentLevel and numOfNodes to start new level
            currentLevel++;
            numOfNodes = 0;

            q.put(endOfLevel);
         }
         else
         {// continuation of current level
            numOfNodes++;

            // put p's children on queue
            if (p.leftChild != null) 
               q.put(p.leftChild);
            if (p.rightChild != null)
               q.put(p.rightChild);
         }
      }
    }
}