import java.util.*;

public abstract class Tree
 { public abstract Object  contents();
   public abstract Tree    subTree(int i);
   public abstract int     fanOut();
   public abstract boolean isEmpty();


   public boolean isLeaf()
    { for(int i = 0; i < this.fanOut(); i++) // 0 .. fanOut-1
         if( ! this.subTree(i).isEmpty() ) return false;
      return true; // every child isEmpty
    }//isLeaf()


   public String toString() // overrides Object
    { if(this.isEmpty()) return "()";
      //else
      StringBuffer strB=new StringBuffer("(");
      Object obj = this.contents();
      if(obj != null) strB.append(obj.toString());
      for(int i = 0; i < this.fanOut(); i++) // for each subtree
         strB.append( this.subTree(i).toString() );
      strB.append(")");
      return strB.toString();
    }//toString()

   public String toString(int selector)
    { if(selector == 1) return this.toString2D("");//see below
      /*else*/ return this.toString(); //default, see above
    }

   private String toString2D(String lhs)
    { if(this.isEmpty()) return "";
      StringBuffer strB = new StringBuffer();
      Object obj = this.contents();  String objStr;
      if(obj == null) objStr = ""; else objStr = obj.toString();
      StringBuffer pad = new StringBuffer(objStr+" |");
      for(int i=0; i < objStr.length(); i++) pad.setCharAt(i, ' ');
      for(int i = this.fanOut()-1; i >= 1; i--)
         strB.append( this.subTree(i).toString2D(lhs + pad.toString()));
      strB.append(lhs + objStr + "-|\n");
      if(this.fanOut() > 0)
         strB.append( this.subTree(0).toString2D(lhs + pad.toString()));
      return strB.toString();
    }//toString2D


   private class Prefix implements Enumeration // see java.util
    { private Stack stck = new Stack();
      public Prefix() { if(!Tree.this.isEmpty()) stck.push(Tree.this); }
      public boolean hasMoreElements() { return ! stck.empty(); }
      public Object nextElement()
       { Tree t = (Tree)stck.peek();  stck.pop();
	 for(int i = t.fanOut() - 1; i >= 0; i--)
	  { Tree ti = t.subTree(i); if(!ti.isEmpty()) stck.push(ti); }
	 return t.contents();
    }  }//Prefix

   public Enumeration prefix() { return new Prefix(); }


   private class Postfix implements Enumeration // see java.util
    { private Enumeration subPostfix;
      private int sti /*sub tree index */,  tfo /* tree fan out */;
      private boolean more;

      public Postfix()
       { sti = -1; subPostfix = null;
	 more = ! Tree.this.isEmpty();
	 if(more) tfo = Tree.this.fanOut(); else tfo = 0;
       }//constructor

      public boolean hasMoreElements() { return more; }

      public Object nextElement()
       { if(subPostfix != null)
	    if(subPostfix.hasMoreElements())
	       return subPostfix.nextElement();
	    else subPostfix = null;
	 //subPostfix == null
	 for(sti++; sti < tfo && Tree.this.subTree(sti).isEmpty(); sti++)
	    { /* skip */ }
         if(sti < tfo) // ! empty ...sti
	  { subPostfix = Tree.this.subTree(sti).postfix();
            return subPostfix.nextElement();
          }
         // else sti >= tfo
	 more = false;  return Tree.this.contents(); // root last
    }  }//Postfix

   public Enumeration postfix() { return new Postfix(); }

 }//Tree

// Lloyd Allison.
