// file: $isip/class/dstr/Tree/Tree.h
// version: $Id: Tree.h 8932 2002-12-22 20:46:07Z parihar $
//

// make sure definitions are made only once
//
#ifndef ISIP_TREE
#define ISIP_TREE

// isip include files
//
#ifndef ISIP_DSTR_BASE
#include <DstrBase.h>
#endif

#ifndef ISIP_SINGLE_LINKED_LIST
#include <SingleLinkedList.h>
#endif

#ifndef ISIP_HASH_TABLE
#include <HashTable.h>
#endif

#ifndef ISIP_STACK
#include <Stack.h>
#endif

#ifndef ISIP_QUEUE
#include <Queue.h>
#endif

#ifndef ISIP_HASH_KEY
#include <HashKey.h>
#endif

#ifndef ISIP_TREE_NODE
#include <TreeNode.h>
#endif

#ifndef ISIP_VECTOR
#include <Vector.h>
#endif

#ifndef ISIP_CONSOLE
#include <Console.h>
#endif

// forward class definitions
//
template<class TObject> class TreeNode;
template<class TObject> class TreeDiagnose;

// Tree: this class implements a Tree data structure using the left child
// right sibling representation.
//
template<class TObject>
class Tree : private DoubleLinkedList< TreeNode<TObject> > {
    
  //---------------------------------------------------------------------------
  //
  // public constants
  //
  //---------------------------------------------------------------------------
public:
  
  // define the class name
  //
  static const String CLASS_NAME;

  //----------------------------------------
  //
  // i/o related constants
  //
  //----------------------------------------  
  
  static const String DEF_PARAM;
  static const String PARAM_ROOT_ITEM;
  static const String PARAM_ROOT_ADJACENT;
  static const String PARAM_NODE_ITEMS;
  static const String PARAM_NODE_ADJACENT;
  
  //----------------------------------------
  //
  // default values and arguments
  //
  //----------------------------------------
  
  // default values
  //
  
  // default arguments to methods
  //
  
  //----------------------------------------
  //
  // error codes
  //
  //----------------------------------------  
  
  //---------------------------------------------------------------------------
  //
  // protected data
  //
  //---------------------------------------------------------------------------
protected:

  // the allocation mode
  //
  DstrBase::ALLOCATION alloc_d;
  
  // define the root of the tree
  //
  TreeNode<TObject> root_d;

  // debugging parameters
  //
  static Integral::DEBUG debug_level_d;

  // define the memory manager
  //  
  static MemoryManager mgr_d;
  
  //---------------------------------------------------------------------------
  //
  // required public methods
  //
  //---------------------------------------------------------------------------
public:
  
  // static methods:
  //  the diagnose method is moved outside the class header file and
  //  defined in the TreeDiagnose.h in order to avoid issues
  //  with preprocessing of the diagnose code.
  //
  static const String& name();
  
  // method: setDebug
  //
  static boolean setDebug(Integral::DEBUG debug_level) {
    debug_level_d = debug_level;
    return true;
  }

  // other debug methods
  //
  boolean debug(const unichar* msg) const;
     
  // destructor/constructor(s)
  //
  ~Tree();
  Tree(DstrBase::ALLOCATION alloc = DstrBase::DEF_ALLOCATION);
  Tree(const Tree<TObject>& copy_Tree);

  // assign method
  //
  boolean assign(const Tree<TObject>& copy_stack);
  
  // method: operator=
  //
  Tree<TObject>& operator=(const Tree<TObject>& arg) {
    assign(arg);
    return *this;
  }

  // equality method
  //
  boolean eq(const Tree<TObject>& arg) const;
  
  // sofSize method
  //
  long sofSize() const;

  // method: read
  //
  boolean read(Sof& sof, long tag) {
    return read(sof, tag, name());
  }
  
  // method: write
  //
  boolean write(Sof& sof, long tag) const {
    return write(sof, tag, name());
  }
  
  // other read methods
  //
  boolean read(Sof& sof, long tag, const String& name);
  boolean readData(Sof& sof, const String& pname = DEF_PARAM,
		   long size = SofParser::FULL_OBJECT, boolean param = true,
                   boolean nested = false);
  
  // other write methods
  //
  boolean write(Sof& sof, long tag, const String& name) const;
  boolean writeData(Sof& sof, const String& pname = DEF_PARAM) const;

  // method: new
  //
  static void* operator new(size_t size) {
    return mgr_d.get();
  }

  // method: new[]
  //
  static void* operator new[](size_t size) {
    return mgr_d.getBlock(size);
  }

  // method: delete
  //
  static void operator delete(void* ptr) {
    mgr_d.release(ptr);
  }

  // method: delete[]
  //
  static void operator delete[](void* ptr) {
    mgr_d.releaseBlock(ptr);
  }

  // method: setGrowSize
  //
  static boolean setGrowSize(long grow_size) {
    return mgr_d.setGrow(grow_size);
  }
    
  // clear method
  //
  boolean clear(Integral::CMODE cmode = Integral::DEF_CMODE);
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  tree manipulation methods
  //
  //---------------------------------------------------------------------------

  // method: getRoot
  //
  TreeNode<TObject>* getRoot() const {
    return (TreeNode<TObject>*)&root_d;
  }

  // method to set the root item
  //
  boolean setRootItem(TObject* obj);
  
  // insert methods
  //
  TreeNode<TObject>* insert(TObject* obj);
  boolean insertChild(TreeNode<TObject>* pnode, TreeNode<TObject>* cnode);

  // remove methods
  //  
  boolean remove();    
  boolean remove(TObject*& obj);

  // item containment methods
  //
  boolean find(const TObject* obj);
  boolean find(const TreeNode<TObject>* node);
  boolean contains(const TObject* obj) const;
  boolean contains(const TreeNode<TObject>* node) const;

  // this method extracts the structure of the tree and places them
  // in two lists. the first list contains the tree node and the second
  // list contains its corresponding children
  //
  boolean get(Vector<Ulong>& root_adj,
	      SingleLinkedList<TObject>& node_obj,
	      SingleLinkedList<Vector<Ulong> >& node_adj);
	      
  // this method uses the extracted structure of the tree in the two
  // lists as a blue print to reconstruct the tree structure
  //
  boolean set(Vector<Ulong>& root_adj,
	      SingleLinkedList<TObject>& node_obj,
	      SingleLinkedList<Vector<Ulong> >& node_adj);
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  tree allocation mode methods
  //
  //---------------------------------------------------------------------------
  
  // method: getAllocationMode
  //
  DstrBase::ALLOCATION getAllocationMode() const {
    return alloc_d;
  }

  // method: setAllocationMode
  //
  boolean setAllocationMode(DstrBase::ALLOCATION alloc) {
    alloc_d = alloc;
    return true;
  }  
  
  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  tree traversal methods
  //
  //---------------------------------------------------------------------------

  // post-order traversal visits the left child first, then the right child,
  // and finally visits the parent node
  //
  boolean postorderTreeTraversal(SingleLinkedList<TreeNode<TObject> >& arg);

  // pre-order traversal visits parent node first, then the left child,
  // and finally visits the right child  
  //
  boolean preorderTreeTraversal(SingleLinkedList<TreeNode<TObject> >& arg);

  // in-order traversal visits left child first, then the parent node,
  // and finally visits the right child  
  //   
  boolean inorderTreeTraversal(SingleLinkedList<TreeNode<TObject> >& arg);

  // level-order traversal visits all nodes at level one (namely the root)
  // before visiting all nodes at level two and so on...
  //
  boolean levelorderTreeTraversal(SingleLinkedList<TreeNode<TObject> >& arg);

  //---------------------------------------------------------------------------
  //
  // class-specific public methods:
  //  double linked list methods
  //
  //---------------------------------------------------------------------------
  
  // the Tree class derives the DoubleLinkedList bases class which
  // is used as the primary underlying container class. to prevent the
  // user from circumventing the Tree's interface and interacting
  // directly with the DoubleLinkedList we use private inheritance.
  // we define here the methods of the DoubleLinkedList interface that
  // the user is permitted access to.
  //
  using DoubleLinkedList< TreeNode<TObject> >::length;
  using DoubleLinkedList< TreeNode<TObject> >::gotoFirst;
  using DoubleLinkedList< TreeNode<TObject> >::gotoNext;
  using DoubleLinkedList< TreeNode<TObject> >::gotoPrev;
  using DoubleLinkedList< TreeNode<TObject> >::getCurr;
  using DoubleLinkedList< TreeNode<TObject> >::getFirst;
  using DoubleLinkedList< TreeNode<TObject> >::getLast;
  using DoubleLinkedList< TreeNode<TObject> >::gotoMark;
  using DoubleLinkedList< TreeNode<TObject> >::setMark;
  using DoubleLinkedList< TreeNode<TObject> >::gotoPosition;
  using DoubleLinkedList< TreeNode<TObject> >::getPosition;
  using DoubleLinkedList< TreeNode<TObject> >::isLast;
  using DoubleLinkedList< TreeNode<TObject> >::isEmpty;
  using DoubleLinkedList< TreeNode<TObject> >::isMarkedElement;
  
  //---------------------------------------------------------------------------
  //
  // private methods
  //
  //---------------------------------------------------------------------------

private:

  // tree traversal iterators
  //
  boolean postorderTreeIterator(Stack<TreeNode<TObject> >& stack);
  boolean preorderTreeIterator(Stack<TreeNode<TObject> >& stack);
  boolean inorderTreeIterator(TreeNode<TObject>* parent,
			      Queue<TreeNode<TObject> >& queue);
  boolean levelorderTreeIterator(SingleLinkedList<TreeNode<TObject> >& arg,
				 Queue<TreeNode<TObject> >& queue);    
  
  // declare friend classes
  //  
  template <class TObject_diagnose> 
  friend class TreeDiagnose;  
};

//-----------------------------------------------------------------------------
//
// we define non-integral constants at the end of class definition for
// templates (for non-templates these are defined in the default constructor)
//      
//-----------------------------------------------------------------------------

// constants: required constants such as the class name
//
template <class TObject>
const String Tree<TObject>::CLASS_NAME(L"Tree");

template <class TObject>
const String Tree<TObject>::DEF_PARAM(L"values");

template <class TObject>
const String Tree<TObject>::PARAM_ROOT_ITEM(L"root_item");

template <class TObject>
const String Tree<TObject>::PARAM_ROOT_ADJACENT(L"root_adjacent");

template <class TObject>
const String Tree<TObject>::PARAM_NODE_ITEMS(L"node_items");

template <class TObject>
const String Tree<TObject>::PARAM_NODE_ADJACENT(L"node_adjacent");

// static instantiations: debug level
//
template <class TObject>
Integral::DEBUG Tree<TObject>::debug_level_d = Integral::NONE;

// static instantiations: the memory manager
//
template <class TObject>
MemoryManager Tree<TObject>::mgr_d(sizeof(Tree<TObject>), CLASS_NAME);

// below are all the methods for the Tree template class
//      

// ---------------------------------------------------------------------
//
// required static methods
//
//----------------------------------------------------------------------

// method: name
//
// arguments: none
//
// return: a static String& containing the class name
//
// this method returns the class name
//
template<class TObject>
const String& Tree<TObject>::name() {
  
  // create the static name string for this class and return it
  //
  static String cname(CLASS_NAME);
  cname.clear();
  cname.concat(CLASS_NAME);
  cname.concat(L"<");
  cname.concat(TObject::name());
  cname.concat(L">");
  
  // return the name
  //
  return cname;
}

// ---------------------------------------------------------------------
//
// required debug methods
//
//----------------------------------------------------------------------

// method: debug
//
// arguments:
//  unichar* msg: (input) information message
//
// return: a boolean value indicating status
//
// this method dumps the contents of an object to the console
// 
template<class TObject>
boolean Tree<TObject>::debug(const unichar* msg_a) const {

  // dump the root node
  //
  root_d.debug(L"root_d");

  // dump the remaining nodes
  //
  DoubleLinkedList< TreeNode<TObject> >::debug(L"nodes");  
  
  // exit gracefully
  // 
  return true;
}

//------------------------------------------------------------------------
//
// required destructor/constructor(s)
//
//-----------------------------------------------------------------------

// method: destructor
//
// arguments: none
//
// return: none
//
template<class TObject>
Tree<TObject>::~Tree() {

  // free memory
  //
  clear();
}

// method: default constructor
//
// arguments:
//  DstrBase::ALLOCATION alloc: (input) the flag to specify whether or not the
//                              item memory is allocated by the node itself
//
// return: none
//
template<class TObject>
Tree<TObject>::Tree(DstrBase::ALLOCATION alloc_a) {

  // set the allocation flag
  //
  alloc_d = alloc_a;

  // set the allocation mode for the underlying container
  //
  DoubleLinkedList< TreeNode<TObject> >::setAllocationMode(DstrBase::USER);
}

// method: copy constructor
//
// arguments:
//  const Tree<TObject>& copy_tree: (input) the Tree to copy
//
// return: none
//
template<class TObject>
Tree<TObject>::Tree(const Tree<TObject>& copy_tree_a) {

  // set the allocation mode for the underlying container
  //
  DoubleLinkedList< TreeNode<TObject> >::setAllocationMode(DstrBase::USER);
  
  // call the assign method to copy the Tree
  //
  assign(copy_tree_a);
}

//------------------------------------------------------------------------
//
// required assign methods
//
//-------------------------------------------------------------------------

// method: assign
//
// arguments:
//  const Tree<TObject>& copy_tree: (input) the Tree to copy
//
// return: a boolean value indicating status
//
// this method copies the contents of the input to this Tree
//
template<class TObject>
boolean Tree<TObject>::assign(const Tree<TObject>& copy_tree_a) {

  // declare local variables
  //
  Vector<Ulong> root_adj;
  SingleLinkedList<TObject> node_obj;
  SingleLinkedList<Vector<Ulong> > node_adj;

  // set the root item
  //
  root_d.assign(copy_tree_a.root_d);
  
  // get the structure of the input tree
  //
  const_cast<Tree<TObject> &>(copy_tree_a).get(root_adj, node_obj, node_adj);

  // set the structure of the current tree
  //
  this->set(root_adj, node_obj, node_adj);
  
  // exit gracefully
  //
  return true;
}

//------------------------------------------------------------------------
//
// required equality methods
//
//------------------------------------------------------------------------

// method: eq
//
// arguments:
//  const Tree<TObject>& compare_tree: (input) the Tree to compare
//
// return: a boolean value indicating status
//
// this method compares two Trees for equivalence. two Trees are equivalent
// if all corresponding items are equivalent
//
template<class TObject>
boolean Tree<TObject>::eq(const Tree<TObject>& compare_tree_a) const {

  // declare local variables
  //
  Vector<Ulong> root_adj_00;
  SingleLinkedList<TObject> node_obj_00;
  SingleLinkedList<Vector<Ulong> > node_adj_00;

  Vector<Ulong> root_adj_01;
  SingleLinkedList<TObject> node_obj_01;
  SingleLinkedList<Vector<Ulong> > node_adj_01;  
  
  // compare the root item
  //
  if (!root_d.eq(compare_tree_a.root_d)) {
    return false;
  }

  // extract the structure of this tree
  //
  const_cast<Tree<TObject> *>(this)->get(root_adj_00, node_obj_00, node_adj_00);
  
  // extract the structure of the input tree
  //  
  const_cast<Tree<TObject> &>(compare_tree_a).get(root_adj_01, node_obj_01, node_adj_01);

  // test the structure for equavalence
  //
  if (!root_adj_00.eq(root_adj_01)) {
    return false;
  }

  if (!node_obj_00.eq(node_obj_01)) {
    return false;
  }

  if (!node_adj_00.eq(node_adj_01)) {
    return false;
  }
  
  // if we have reached this far then they must be equal
  //
  return true;
}

//-------------------------------------------------------------------------
//
// required memory management methods
//
//-------------------------------------------------------------------------

// method: clear
//
// arguments: 
// Integral::CMODE cmode_a: (input) clear mode
//  
// return: a boolean value indicating status
//
// this method clears the contents of the list by the setting of cmode_a
//
template<class TObject>
boolean Tree<TObject>::clear(Integral::CMODE cmode_a) {

  // for RETAIN mode, call clear on every object but do not change
  // topology. for FREE mode we also need to call clear(FREE) on all
  // TObjects, but we will also delete the topology below.
  //
  if ((cmode_a == Integral::RETAIN) || (cmode_a == Integral::FREE)) {
    for (boolean more = gotoFirst(); more; more = gotoNext()) {
      ((TObject*)(getCurr()->getItem()))->clear(cmode_a);
    }

    if (root_d.getItem() != (TObject*)NULL) {
      root_d.getItem()->clear(cmode_a);
    }
  }

  // for RETAIN mode we are done, make no changes to topology
  //
  if (cmode_a == Integral::RETAIN) {
    return true;
  }

  // when the graph is in SYSTEM-allocation mode or the clear mode is
  // free we need to delete the TObject
  //
  for (boolean more = gotoFirst(); more; more = gotoNext()) {
    if ((alloc_d == SYSTEM) || (cmode_a == Integral::FREE)) {
      
      // delete the TObject
      //
      delete getCurr()->getItem();
    }
    
    // set the pointer to null
    //
    ((TreeNode<TObject>*)getCurr())->setItem((TObject*)NULL);
  }

  if ((alloc_d == SYSTEM) || (cmode_a == Integral::FREE)) {

    // delete the TObject
    //
    if (root_d.getItem() != (TObject*)NULL) {    
      delete root_d.getItem();
    }
  }

  // set the pointer to null
  //
  root_d.setItem((TObject*)NULL);
    
  // clear the tree nodes list
  //
  DoubleLinkedList< TreeNode<TObject> >::setAllocationMode(DstrBase::SYSTEM);
  DoubleLinkedList< TreeNode<TObject> >::clear(Integral::RESET);
  DoubleLinkedList< TreeNode<TObject> >::setAllocationMode(DstrBase::USER);
  
  // exit gracefully
  //
  return true;
}

//------------------------------------------------------------------------
//
// class-specific public methods:
//  i/o methods
//
//------------------------------------------------------------------------

// method: read
//
// arguments:
//  Sof& sof: (input) sof file object
//  long tag: (input) sof object instance tag
//  const String& name: (input) sof object instance name
//
// return: a boolean value indicating status
//
// this method has the object read itself from an Sof file according
// to the specified name and tag
//
template <class TObject>
boolean Tree<TObject>::read(Sof& sof_a, long tag_a, const String& name_a) {

  // exit gracefully
  //
  return true;
}

// method: readData
//
// arguments:
//  Sof& sof: (input) sof file object
//  const String& pname: (input) parameter name
//  long size: (input) size in bytes of object (or FULL_OBJECT)
//  boolean param: (input) is the parameter name in the file?
//  boolean nested: (input) are we nested?
//
// return: a boolean value indicating status
//
// this method has the object read itself from an Sof file. it assumes
// that the Sof file is already positioned correctly
//
template <class TObject>
boolean Tree<TObject>::readData(Sof& sof_a, const String& pname_a,
			      long size_a, boolean param_a, boolean nested_a) {

  // exit gracefully
  //
  return true;
}

// method: sofSize
//
// arguments: none
//
// return: size of object
//
// this method returns the size of the object in the Sof file and is
// used for binary write
//
template <class TObject>
long Tree<TObject>::sofSize() const {

  // return the size
  //
  return bytes;
}

// method: write
//
// arguments:
//  Sof& sof: (input) sof file object
//  long tag: (input) sof object instance tag
//  const String& name: (input) sof object instance name
//
// return: a boolean value indicating status
//
// this method has the object write itself to an Sof file
//
template <class TObject>
boolean Tree<TObject>::write(Sof& sof_a, long tag_a,
			     const String& name_a) const {

  // exit gracefully
  //
  return true;
}

//------------------------------------------------------------------------
//
// class-specific public methods:
//  tree manipulation methods
//
//------------------------------------------------------------------------

// method: setRootItem
//
// arguments:
//  TObject* obj: (input) object to be inserted in the tree
//
// return: a boolean value indicating status
//
// this method inserts the input object as the root item
//
template<class TObject>
boolean Tree<TObject>::setRootItem(TObject* obj_a) {

  // perform error checking
  //
  if (obj_a == (TObject*)NULL) {
    Error::handle(name(), L"insert", Error::ARG, __FILE__, __LINE__);
    return (TreeNode<TObject>*)NULL;
  }
  
  // declare local variables and allocate a new TreeNode object
  //
  TObject* new_obj = (TObject*)NULL;

  // when the tree is in SYSTEM mode make a copy of the object
  //
  if (alloc_d == SYSTEM) {
    new_obj = new TObject(*obj_a);
  }

  // assign the object pointer when in USER mode
  //
  else {
    new_obj = obj_a;
  }

  // set the object on the tree node
  //
  root_d.setItem(new_obj);

  // exit gracefully
  //
  return true;
}
  
// method: insert
//
// arguments:
//  TObject* obj: (input) object to be inserted in the tree
//
// return: a boolean value indicating status
//
// this method inserts the input object into the tree structure
//
template<class TObject>
TreeNode<TObject>* Tree<TObject>::insert(TObject* obj_a) {

  // perform error checking
  //
  if (obj_a == (TObject*)NULL) {
    Error::handle(name(), L"insert", Error::ARG, __FILE__, __LINE__);
    return (TreeNode<TObject>*)NULL;
  }
  
  // declare local variables and allocate a new TreeNode object
  //
  TObject* new_obj = (TObject*)NULL;
  TreeNode<TObject>* node = new TreeNode<TObject>();

  // when the tree is in SYSTEM mode make a copy of the object
  //
  if (alloc_d == SYSTEM) {
    new_obj = new TObject(*obj_a);
  }

  // assign the object pointer when in USER mode
  //
  else {
    new_obj = obj_a;
  }

  // set the object on the tree node
  //
  node->setItem(new_obj);

  // add vertex on the graph
  //
  DoubleLinkedList< TreeNode<TObject> >::insert(node);

  // exit gracefully
  //
  return node;  
}

// method: insertChild
//
// arguments:
//  TreeNode<TObject>* pnone: (input) parent tree node
//  TreeNode<TObject>* cnone: (input) child tree node
//
// return: a boolean value indicating status
//
// this method sets the child node as one of the children of the parent node
//
template<class TObject>
boolean Tree<TObject>::insertChild(TreeNode<TObject>* pnode_a,
				    TreeNode<TObject>* cnode_a) {

  // declare local variables
  //
  TreeNode<TObject>* node = (TreeNode<TObject>*)NULL;
  
  // verify that the input is valid
  //
  if ((pnode_a == (TreeNode<TObject>*)NULL) ||
      (cnode_a == (TreeNode<TObject>*)NULL)) {
    return Error::handle(name(), L"insertChild", Error::ARG, __FILE__, __LINE__);
  }

  // child cannot have multiple children
  //
  if (cnode_a->getParent() != (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"insertChild", Error::ARG, __FILE__, __LINE__);
  }
  
  // if the left child is null set the child node as the left child
  //
  if (pnode_a->getLeftChild() == (TreeNode<TObject>*)NULL) {
    pnode_a->setLeftChild(cnode_a);
  }

  // else set the child node as a right sibling
  //  
  else {

    // if the right sibling is null set the child node as the right sibling
    //
    if ((node = pnode_a->getLeftChild()->getRightSibling())
	== (TreeNode<TObject>*)NULL) {
      pnode_a->getLeftChild()->setRightSibling(cnode_a);
    }

    // insert the child node as one of the right siblings of the left child
    //    
    else {

      while (node->getRightSibling() != (TreeNode<TObject>*)NULL) {
	node = node->getRightSibling();
      }
      node->setRightSibling(cnode_a);
    }
  }

  // set the parent of the child node
  //
  cnode_a->setParent(pnode_a);
  
  // increment the degree of the parent node
  //  
  pnode_a->increment();
  
  // exit gracefully
  //
  return true;
}

// method: remove
//
// arguments: none
//
// return: a boolean value indicating status
//
// this method removes the current tree node form the tree structure
//
template<class TObject>
boolean Tree<TObject>::remove() {

  // make sure the current tree node is valid
  //
  TreeNode<TObject>* this_node = (TreeNode<TObject>*)this->getCurr();  
  if (this_node == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"remove", Error::ARG, __FILE__, __LINE__);
  }
  
  // unlink the right siblings that reference this node
  //
  TreeNode<TObject>* pnode = this_node->getParent();  
  if (pnode != (TreeNode<TObject>*)NULL) {
    TreeNode<TObject>* tnode = pnode->getLeftChild();
    while (tnode != (TreeNode<TObject>*)NULL) {
      if (tnode->getRightSibling() == this_node) {
	tnode->setRightSibling(this_node->getRightSibling());
	break;
      }
      tnode = tnode->getRightSibling();
    }
  }
      
  // unlink the children that reference this node
  //
  TreeNode<TObject>* lnode = this_node->getLeftChild();
  if (lnode != (TreeNode<TObject>*)NULL) {
    lnode->setParent((TreeNode<TObject>*)NULL);

    TreeNode<TObject>* tnode = lnode->getRightSibling();
    while(tnode != (TreeNode<TObject>*)NULL) {
      tnode->setParent((TreeNode<TObject>*)NULL);
      tnode = tnode->getRightSibling();
    }
  }
      
  // clear the contents of the tree node
  //
  this_node->clear(Integral::FREE);

  // decrement the degree of the parent node
  //
  if (pnode != (TreeNode<TObject>*)NULL) {
    pnode->decrement();
  }
  
  // remove the object from the linked list
  //
  boolean status = false;
  TreeNode<TObject>* tree_node;
  status = DoubleLinkedList< TreeNode<TObject> >::remove(tree_node);
  delete tree_node;

  return status;  
}

// method: remove
//
// arguments:
//  TObject*& obj: (input) object to be removed
//
// return: a boolean value indicating status
//
// this method removes the input tree node form the tree structure
//
template<class TObject>
boolean Tree<TObject>::remove(TObject*& obj_a) {

  // make sure the current tree node is valid
  //
  TreeNode<TObject>* this_node = (TreeNode<TObject>*)this->getCurr();  
  if (this_node == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"remove", Error::ARG, __FILE__, __LINE__);
  }
  
  // make sure memory is allocated if we are SYSTEM-allocated
  //
  if ((alloc_d == SYSTEM) && (obj_a == (TObject*)NULL)) {
    return Error::handle(name(), L"remove", Error::ARG, __FILE__, __LINE__);
  }

  // when in SYSTEM mode make a copy of the object data
  //
  if (alloc_d == SYSTEM) {
    obj_a->assign(*this_node->getItem());
    delete this_node->getItem();
  }

  // when in USER mode assign the object pointer
  //
  else {
    obj_a = this_node->getItem();
  }

  // unlink the right siblings that reference this node
  //
  TreeNode<TObject>* pnode = this_node->getParent();  
  if (pnode != (TreeNode<TObject>*)NULL) {
    TreeNode<TObject>* tnode = pnode->getLeftChild();
    while (tnode != (TreeNode<TObject>*)NULL) {
      if (tnode->getRightSibling() == this_node) {
	tnode->setRightSibling(this_node->getRightSibling());
	break;
      }
      tnode = tnode->getRightSibling();      
    }
  }
      
  // unlink the children that reference this node
  //
  TreeNode<TObject>* lnode = this_node->getLeftChild();
  if (lnode != (TreeNode<TObject>*)NULL) {
    lnode->setParent((TreeNode<TObject>*)NULL);

    TreeNode<TObject>* tnode = lnode->getRightSibling();
    while(tnode != (TreeNode<TObject>*)NULL) {
      tnode->setParent((TreeNode<TObject>*)NULL);
      tnode = tnode->getRightSibling();
    }
  }

  // clear the contents of the tree node
  //
  this_node->clear();

  // decrement the degree of the parent node
  //
  if (pnode != (TreeNode<TObject>*)NULL) {
    pnode->decrement();
  }
  
  // remove the object from the linked list
  //
  boolean status = false;
  TreeNode<TObject>* tree_node;
  status = DoubleLinkedList< TreeNode<TObject> >::remove(tree_node);
  delete tree_node;

  return status;  
}

// method: contains
//
// arguments:
//  TObject* obj: (input) the object to be found
//
// return: a boolean value indicating status
//
// this method determines if the input object is in the list of vertices
//
template<class TObject>
boolean Tree<TObject>::contains(const TObject* obj_a) const {

  // check if the input object is NULL
  //
  if (obj_a == (TObject*)NULL) {
    return Error::handle(name(), L"contains", Error::ARG, __FILE__, __LINE__);
  }

  // save the current position
  //
  long old_pos = const_cast<Tree<TObject>* >(this)->getPosition();

  // temporary variables
  //
  boolean obj_found = false;
  boolean more_nodes = const_cast<Tree<TObject>* >(this)->gotoFirst();
  
  // search from the beginning for the item
  //
  while (!obj_found && more_nodes) {

    // get the current node
    //
    TreeNode<TObject>* this_node =
     (TreeNode<TObject>*) const_cast<Tree<TObject>* >(this)->getCurr();

    // get the object contained in the node
    //
    TObject* this_obj = this_node->getItem();
    
    // compare the objects for equality
    //
    obj_found = obj_a->eq(*this_obj);
    
    if (!obj_found) {
      more_nodes = const_cast<Tree<TObject>* >(this)->gotoNext();
    }
  }

  // restore the previous position
  //
  const_cast<Tree<TObject>* >(this)->gotoPosition(old_pos);
  
  // return whether or not the object was found
  //
  return obj_found;  
}

// method: contains
//
// arguments:
//  TreeNode<TObject>* node: (input) the node to be found
//
// return: a boolean value indicating status
//
// this method determines if the input node is in the list of
// vertices. note that we can't just call list contains since we only
// want to compare pointers, not values.
//
template<class TObject>
boolean
Tree<TObject>::contains(const TreeNode<TObject>* node_a) const {

  // check if the input object is NULL
  //
  if (node_a == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"contains", Error::NULL_ARG,
			 __FILE__, __LINE__);
  }

  // save the current position
  //
  long old_pos = const_cast<Tree<TObject>* >(this)->getPosition();

  // temporary variables
  //
  boolean node_found = false;
  boolean more_nodes = const_cast<Tree<TObject>* >(this)->gotoFirst();
  
  // search from the beginning for the item
  //
  while (!node_found && more_nodes) {

    // get the current node
    //
    TreeNode<TObject>* this_node =
     (TreeNode<TObject>*) const_cast<Tree<TObject>* >(this)->getCurr();

    // compare the pointers for equality
    //
    if (this_node == node_a) {
      node_found = true;
    }
    
    if (!node_found) {
      more_nodes = const_cast<Tree<TObject>* >(this)->gotoNext();
    }
  }

  // restore the previous state
  //
  const_cast<Tree<TObject>* >(this)->gotoPosition(old_pos);
  
  // return whether or not the object was found
  //
  return node_found;
}

// method: find
//
// arguments:
//  TObject* obj: (input) the object to be found
//
// return: a boolean value indicating status
//
// this method determines if the input object is in the list of vertices
// and moves the list current pointer to the first occurance of the object
//
template<class TObject>
boolean Tree<TObject>::find(const TObject* obj_a) {

  // check if the input object is NULL
  //
  if (obj_a == (TObject*)NULL) {
    return Error::handle(name(), L"find", Error::NULL_ARG, __FILE__, __LINE__);
  }

  // save the current position
  //
  this->setMark();

  // temporary variables
  //
  boolean obj_found = false;
  boolean more_nodes = this->gotoFirst();
  
  // search from the beginning for the item
  //
  while (!obj_found && more_nodes) {

    // get the current node
    //
    TreeNode<TObject>* this_node = (TreeNode<TObject>*)this->getCurr();

    // get the object contained in the node
    //
    TObject* this_obj = this_node->getItem();
    
    // compare the objects for equality
    //
    obj_found = obj_a->eq(*this_obj);
    
    if (!obj_found) {
      more_nodes = this->gotoNext();
    }
  }

  if (!obj_found) {
    this->gotoMark();
  }
  
  // return whether or not the object was found
  //
  return obj_found;
}

// method: find
//
// arguments:
//  TreeNode<TObject>* node: (input) the node to be found
//
// return: a boolean value indicating status
//
// this method determines if the input node is in the list of
// vertices. if found the node list is left pointing to the
// node. note that we can't just call list contains since we only
// want to compare pointers, not values.
//
template<class TObject>
boolean Tree<TObject>::find(const TreeNode<TObject>* node_a) {

  // check if the input object is NULL
  //
  if (node_a == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"find", Error::NULL_ARG,
			 __FILE__, __LINE__);
  }

  // save the current position
  //
  long old_pos = const_cast<Tree<TObject>* >(this)->getPosition();

  // temporary variables
  //
  boolean node_found = false;
  boolean more_nodes = const_cast<Tree<TObject>* >(this)->gotoFirst();
  
  // search from the beginning for the item
  //
  while (!node_found && more_nodes) {

    // get the current node
    //
    TreeNode<TObject>* this_node =
      (TreeNode<TObject>*)const_cast<Tree<TObject>* >(this)->getCurr();

    // compare the pointers for equality
    //
    if (this_node == node_a) {
      node_found = true;
    }
    
    if (!node_found) {
      more_nodes = const_cast<Tree<TObject>* >(this)->gotoNext();
    }
  }

  // restore the previous state if the node was not found
  //
  if (!node_found) {
    const_cast<Tree<TObject>* >(this)->gotoPosition(old_pos);
  }
  
  // return whether or not the object was found
  //
  return node_found;
}

// method: set
//
// arguments:
//  Vector<Ulong>& root_adj: (input) adjecent nodes to root node
//  SingleLinkedList<TObject>& node_obj: (input) tree node items
//  SingleLinkedList<Vector<Ulong> >& node_adj: (input) adjacent nodes to tree nodes
//  
// return: a boolean value indicating status
//
// this method uses the extracted structure of the tree in the two
// lists as a blue print to reconstruct the tree structure
//
template<class TObject>
boolean Tree<TObject>::set(Vector<Ulong>& root_adj_a,
			   SingleLinkedList<TObject>& node_obj_a,
			   SingleLinkedList<Vector<Ulong> >& node_adj_a) {

  // declare local variables
  //
  Ulong index = 0;
  Vector<Ulong>* indices = (Vector<Ulong>*)NULL;
  TreeNode<TObject>* node = (TreeNode<TObject>*)NULL;
  HashTable<Ulong, TreeNode<TObject> > khash(DstrBase::USER);
  SingleLinkedList<TreeNode<TObject> > nodes(DstrBase::USER);

  // clear the contents of the tree structure
  //
  clear();

  // loop over each element in the item list
  //    
  for (boolean more = node_obj_a.gotoFirst(); more; more = node_obj_a.gotoNext()) {
    node = insert(node_obj_a.getCurr());
    khash.insert(index, node);
    nodes.insert(node);
    index++;
  }

  // connect the root node to its adjacent nodes
  //
  for (long i=0; i < root_adj_a.length(); i++) {
    insertChild(this->getRoot(), khash.get(root_adj_a(i)));
  }

  // connect the remaining tree nodes to its adjacent nodes
  //
  nodes.gotoFirst();
  for (boolean more = node_adj_a.gotoFirst(); more;
       more = node_adj_a.gotoNext()) {
    indices = node_adj_a.getCurr();
    for (long i=0; i < indices->length(); i++) {
      insertChild(nodes.getCurr(), khash.get((*indices)(i)));
    }
    nodes.gotoNext();    
  }
    
  // exit gracefully
  //
  return true;
}

// method: get
//
// arguments:
//  Vector<Ulong>& root_adj: (output) adjecent nodes to root node
//  SingleLinkedList<TObject>& node_obj: (output) tree node items
//  SingleLinkedList<Vector<Ulong> >& node_adj: (output) adjacent nodes to tree nodes
//  
// return: a boolean value indicating status
//
// this method extracts the structure of the tree and places them
// in two lists. the first list contains the tree node and the second
// list contains its corresponding children
//
template<class TObject>
boolean Tree<TObject>::get(Vector<Ulong>& root_adj_a,
			   SingleLinkedList<TObject>& node_obj_a,
			   SingleLinkedList<Vector<Ulong> >& node_adj_a) {

  // declare local variables
  //
  Ulong index = 0;
  Vector<Ulong> indices;
  HashKey<TreeNode<TObject> > hashkey;
  HashTable<HashKey<TreeNode<TObject> >, Ulong> khash;
  TreeNode<TObject>* this_node = (TreeNode<TObject>*)NULL;

  // save the current state of the list
  //
  this->setMark();

  // make sure that the list of node object are in USER mode
  //
  node_obj_a.setAllocationMode(DstrBase::USER);
   
  // add the tree node items to the list
  //
  for (boolean more = this->gotoFirst(); more; more = this->gotoNext()) {

    // add the tree node to the list
    //
    node_obj_a.insert(this->getCurr()->getItem());

    // associate a unique number with the tree node
    //
    hashkey.assign(this->getCurr());
    khash.insert(hashkey, &index);

    // increment the index
    //
    index++;
  }

  // add the nodes adjacent to the root to the list
  //
  this_node = this->getRoot();
  if (this_node == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__);
  }
    
  // get the degree of the root node
  //
  long degree = this_node->degree();
  
  if (degree > 0) {
    
    // set the length of the vector to the degree of the node
    //
    root_adj_a.setLength(degree);
    
    // add the position of the left child to the vector
    //
    long pos = 0;      
    TreeNode<TObject>* lnode = this_node->getLeftChild();
    
    if (lnode != (TreeNode<TObject>*)NULL) {

      hashkey.assign(lnode);
      root_adj_a(pos++) = *(khash.get(hashkey));
      
      // add the positions of the right siblings to the vector
      //	
      TreeNode<TObject>* rnode = lnode->getRightSibling();

      while (rnode != (TreeNode<TObject>*)NULL) {

	hashkey.assign(rnode);
	root_adj_a(pos++) = *(khash.get(hashkey));
	rnode = rnode->getRightSibling();
      }
    }     
  }
  
  // add the nodes adjacent to the nodes in the tree to the list
  //
  for (boolean more = this->gotoFirst(); more; more = this->gotoNext()) {

    // get the current tree node
    //
    this_node = this->getCurr();
    if (this_node == (TreeNode<TObject>*)NULL) {
      return Error::handle(name(), L"get", Error::ARG, __FILE__, __LINE__);
    }

    // clear the previous list of indices
    //
    indices.clear();
    
    // get the degree of the current tree node
    //
    long degree = this_node->degree();
    
    if (degree > 0) {

      // set the length of the vector to the degree of the node
      //
      indices.setLength(degree);

      // add the position of the left child to the vector
      //
      long pos = 0;      
      TreeNode<TObject>* lnode = this_node->getLeftChild();
      
      if (lnode != (TreeNode<TObject>*)NULL) {
	
	hashkey.assign(lnode);
	indices(pos++) = *(khash.get(hashkey));

	// add the positions of the right siblings to the vector
	//	
	TreeNode<TObject>* rnode = lnode->getRightSibling();
	
	while (rnode != (TreeNode<TObject>*)NULL) {
	  
	  hashkey.assign(rnode);
	  indices(pos++) = *(khash.get(hashkey));
	  rnode = rnode->getRightSibling();
	}
      }
    }

    // add the vector of indices to the list
    //
    node_adj_a.insert(&indices);          
  }
  
  // restore the original state of the list
  //
  this->gotoMark();

  // exit gracefully
  //
  return true;
}

//------------------------------------------------------------------------
//
// class-specific public methods:
//  tree traversal methods
//
//------------------------------------------------------------------------

// method: postorderTreeTraversal
//
// arguments:
//  SingleLinkedList<TreeNode<TObject> >& arg: (output) traversed nodes in the tree
//  
// return: a boolean value indicating status
//
// post-order traversal visits the left child first, then the right child,
// and finally visits the parent node
//
template <class TObject>
boolean Tree<TObject>::postorderTreeTraversal(SingleLinkedList<TreeNode<TObject> >& arg_a) {

  // declare local variables
  //
  Stack<TreeNode<TObject> > stack(DstrBase::USER);

  // get the root of the tree
  //
  TreeNode<TObject>* current = this->getRoot();

  if (current == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"postorderTreeTraversal", Error::ARG, __FILE__, __LINE__);
  }
  
  // push the root on the stack
  //
  stack.push(current);
  
  // recursively descend down the tree and visit the children in order
  //
  postorderTreeIterator(stack);

  // insert elements of the stack into the list
  //
  while(!stack.isEmpty()) {
    arg_a.insert(stack.pop());
  }
  
  // exit gracefully
  //
  return true;
}

// method: postorderTreeIterator
//
// arguments:
//  Stack<TreeNode<TObject> >& stack: (input) input stack
//  
// return: a boolean value indicating status
//
// post-order traversal iterator method
//
template <class TObject>
boolean Tree<TObject>::postorderTreeIterator(Stack<TreeNode<TObject> >& stack_a) {

  // verify inputs
  //
  if (stack_a.isEmpty()) {
    return Error::handle(name(), L"postorderTreeIterator", Error::ARG, __FILE__, __LINE__);
  }

  // get the item on the top of the stack
  //
  TreeNode<TObject>* current = stack_a.peek();

  if (current == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"postorderTreeIterator", Error::ARG, __FILE__, __LINE__);
  }

  // get the children associated with the current tree node
  //
  DoubleLinkedList<TreeNode<TObject> > list(DstrBase::USER);
  TreeNode<TObject>* child = current->getLeftChild();
  
  if (child != (TreeNode<TObject>*)NULL) {

    list.insert(child);
    child = child->getRightSibling();
    
    while(child != (TreeNode<TObject>*)NULL) {
      list.insert(child);
      child = child->getRightSibling();
    }
  }

  // recursively descend down the tree and visit the children in order
  //
  for (boolean more = list.gotoLast(); more; more = list.gotoPrev()) {
    stack_a.push(list.getCurr());
    postorderTreeIterator(stack_a);
  }

  // exit gracefully
  //
  return true;
}

// method: preorderTreeTraversal
//
// arguments:
//  SingleLinkedList<TreeNode<TObject> >& arg: (output) traversed nodes in the tree
//  
// return: a boolean value indicating status
//
// pre-order traversal visits parent node first, then the left child,
// and finally visits the right child  
//
template <class TObject>
boolean Tree<TObject>::preorderTreeTraversal(SingleLinkedList<TreeNode<TObject> >& arg_a) {

  // declare local variables
  //
  Stack<TreeNode<TObject> > stack(DstrBase::USER);

  // get the root of the tree
  //
  TreeNode<TObject>* current = this->getRoot();

  if (current == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"postorderTreeTraversal", Error::ARG, __FILE__, __LINE__);
  }
  
  // push the root on the stack
  //
  stack.push(current);
  
  // recursively descend down the tree and visit the children in order
  //
  preorderTreeIterator(stack);

  // insert elements of the stack into the list
  //
  while(!stack.isEmpty()) {
    arg_a.insert(stack.pop());
  }
  arg_a.reverse();
  
  // exit gracefully
  //
  return true;
}

// method: preorderTreeIterator
//
// arguments:
//  Stack<TreeNode<TObject> >& stack: (input) input stack
//  
// return: a boolean value indicating status
//
// post-order traversal iterator method
//
template <class TObject>
boolean Tree<TObject>::preorderTreeIterator(Stack<TreeNode<TObject> >& stack_a) {

  // verify inputs
  //
  if (stack_a.isEmpty()) {
    return Error::handle(name(), L"preorderTreeIterator", Error::ARG, __FILE__, __LINE__);
  }

  // get the item at the fornt of the stack
  //
  TreeNode<TObject>* current = stack_a.peek();

  if (current == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"preorderTreeIterator", Error::ARG, __FILE__, __LINE__);
  }

  // get the children associated with the current tree node
  //
  DoubleLinkedList<TreeNode<TObject> > list(DstrBase::USER);
  TreeNode<TObject>* child = current->getLeftChild();
  
  if (child != (TreeNode<TObject>*)NULL) {

    list.insert(child);
    child = child->getRightSibling();
    
    while(child != (TreeNode<TObject>*)NULL) {
      list.insert(child);
      child = child->getRightSibling();
    }
  }

  // recursively descend down the tree and visit the children in order
  //
  for (boolean more = list.gotoFirst(); more; more = list.gotoNext()) {
    stack_a.push(list.getCurr());
    preorderTreeIterator(stack_a);
  }
  
  // exit gracefully
  //
  return true;
}

// method: inorderTreeIterator
//
// arguments:
//  TreeNode<TObject>* parent: (input) parent tree node
//  Queue<TreeNode<TObject> >& queue: (input) input queue
//  
// return: a boolean value indicating status
//
// post-order traversal iterator method
//
template <class TObject>
boolean Tree<TObject>::inorderTreeIterator(TreeNode<TObject>* parent_a, Queue<TreeNode<TObject> >& queue_a) {

  // verify the inputs
  //
  if (parent_a == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"inorderTreeIterator", Error::ARG, __FILE__, __LINE__);
  }
  
  // visit the left child
  //
  TreeNode<TObject>* child = parent_a->getLeftChild();
  
  if (child != (TreeNode<TObject>*)NULL) {
    inorderTreeIterator(child, queue_a);
  }
  
  // add the parent to the queue
  //
  queue_a.add(parent_a);
  
  // visit the right children
  //
  if (child != (TreeNode<TObject>*)NULL) {
    child = child->getRightSibling();
    while (child != (TreeNode<TObject>*)NULL) {
      inorderTreeIterator(child, queue_a);
      child = child->getRightSibling();      
    }
  }
  
  // exit gracefully
  //
  return true;
}

// method: inorderTreeTraversal
//
// arguments:
//  SingleLinkedList<TreeNode<TObject> >& arg: (output) traversed nodes in the tree
//  
// return: a boolean value indicating status
//
// in-order traversal visits left child first, then the parent node,
// and finally visits the right child
//
template <class TObject>
boolean Tree<TObject>::inorderTreeTraversal(SingleLinkedList<TreeNode<TObject> >& arg_a) {

  // declare local variables
  //
  Queue<TreeNode<TObject> > queue(DstrBase::USER);

  // get the root of the tree
  //
  TreeNode<TObject>* current = this->getRoot();

  if (current == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"postorderTreeTraversal", Error::ARG, __FILE__, __LINE__);
  }
  
  // recursively descend down the tree and visit the children in order
  //
  inorderTreeIterator(current, queue);

  // insert elements of the queue into the list
  //
  while(!queue.isEmpty()) {
    arg_a.insert(queue.remove());
  }

  // exit gracefully
  //
  return true;
}

// method: levelorderTreeTraversal
//
// arguments:
//  SingleLinkedList<TreeNode<TObject> >& arg: (output) traversed nodes in the tree
//  
// return: a boolean value indicating status
//
// level-order traversal visits all nodes at level one (namely the root)
// before visiting all nodes at level two and so on...
//
template <class TObject>
boolean Tree<TObject>::levelorderTreeTraversal(SingleLinkedList<TreeNode<TObject> >& arg_a) {

  // declare local variables
  //
  Queue<TreeNode<TObject> > queue(DstrBase::USER);

  // get the root of the tree
  //
  TreeNode<TObject>* current = this->getRoot();

  if (current == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"postorderTreeTraversal", Error::ARG, __FILE__, __LINE__);
  }
  
  // insert the root node in the queue
  //
  queue.add(current);

  // call the iterator as long as the queue is not empty
  //
  while (!queue.isEmpty()) {
    levelorderTreeIterator(arg_a, queue);
  }
  
  // exit gracefully
  //
  return true;
}

// method: levelorderTreeIterator
//
// arguments:
//  SingleLinkedList<TreeNode<TObject> >& arg: (output) traversed nodes in the tree
//  Queue<TreeNode<TObject> >& queue: (input) input queue
//  
// return: a boolean value indicating status
//
// post-order traversal iterator method
//
template <class TObject>
boolean Tree<TObject>::levelorderTreeIterator(SingleLinkedList<TreeNode<TObject> >& arg_a, Queue<TreeNode<TObject> >& queue_a) {

  // verify inputs
  //
  if (queue_a.isEmpty()) {
    return Error::handle(name(), L"levelorderTreeIterator", Error::ARG, __FILE__, __LINE__);
  }

  // get the parent
  //
  TreeNode<TObject>* parent = queue_a.remove();

  if (parent == (TreeNode<TObject>*)NULL) {
    return Error::handle(name(), L"levelorderTreeIterator", Error::ARG, __FILE__, __LINE__);
  }
  
  // visit the children
  //
  TreeNode<TObject>* child = parent->getLeftChild();
  
  if (child != (TreeNode<TObject>*)NULL) {
    queue_a.add(child);
  }

  if (child != (TreeNode<TObject>*)NULL) {
    child = child->getRightSibling();
    while (child != (TreeNode<TObject>*)NULL) {
      queue_a.add(child);
      child = child->getRightSibling();      
    }
  }
  
  // insert the parent in the list
  //
  arg_a.insert(parent);
  
  // exit gracefully
  //
  return true;
}

// end of include file
//
#endif
