Project 5: Thread-Based BST Iterators

Threaded iterators for BST-based OAA and Map.

Revision dated 06/19/17

Educational Objectives: After completing this assignment, the student should be able to accomplish the following:

Background Knowledge Required: Be sure that you have mastered the material in these chapters before beginning the assignment:
Iterators, Introduction to Sets, Introduction to Maps, Binary Search Trees, Balanced BSTs, and BST Iterators.

Operational Objectives: Implement class templates ConstThreadedMapIterator and ThreadedMapIterator and use these classes to complete the implementations of the class template Map_Threaded.

Deliverables:

map_bst_threaded.h   # Map_BST class template
mapiter_threaded.h   # ConstThreadedMapIterator and ThreadedMapIterator class templates
wordbench3.h         # refactors wordbench2 using fsu::Map_Threaded
wordbench3.cpp       #     "         "        "        "
wordify.cpp          # same file as used for previous project - submitted for convenience
makefile.wb3         # makefile builds fmap.x, mmap.x, and wb3.x
log.txt              # your project work log

Discussion

This project explores the addition of Iterator classes associated with the Ordered Associative Array (OAA) class that was the subject of the previous project. Recall in the previous project, we did not have iterators, but nevertheless created a servicable Map-like container supporting the associative array API (Put, Get, Retrieve). We had to go to extraordinary lengths to obtain a useful traversal, and we were handicapped by the lack of equality operator among OAA objects. We had no way to make sense out of the fundamental Table operation Includes. (But Retrieve is a useful work-around.) Features we will easily obtain using iterators include the following:

  1. Includes method, returning an Iterator object
  2. Operators ==() and !=() defined among Map objects
  3. The Standard Traversal is operational

And we may put aside the special methods for traverals and Display and their recursive implementations. The two tools are compared in the following table.

 Associative Array API
 Put(key,data)    // unimodal insert of (key,data) pair; alias for Insert
 &data = Get(key) // returns &data stored at key; ensures key exists in table
 bool Retrieve(key,&data) const // if true, &data references data stored with key 
 Remove(key) or ( Erase(key) and Rehash() )
 
 Table API
 Insert(key,data)  // unimodal insert of (key,data); alias for Put
 iter = Includes(key)  // returns iter to key if found, End() otherwise (const and non-const) 
 Begin() and End() // supporting bidirectional iterators (const and non-const versions)
 Remove(key) or ( Erase(key) and Rehash() )
 
Both APIs equipped with the usual container boiler plate: Empty, Size, Clear, Constructors, Destructor, operator=

In practice, one has either OAA nicknamed "Table Lite", the iterator-free associative array, or Map nicknamed "Full Table" or "Dictionary", which includes both Associative Array and Table APIs.

One may wonder about code bloat - throwing unwanted operations into the executable code. A big advantage of using templates is that a function template is not translated to object code unless it is actually called in the program. For class templates, this means that unused member functions are not compiled. This makes it sensible and convenient to have both the Associative Array API and the Table API supported by the Map container.

Varieties of Iterators

With a sequential structure such as a list, there is one obvious way for an iterator to go through the elements, from front to back. In a Set or Map structure, the "correct" order is neither unique nor obvious. When using any of the BST implementations, any kind of traversal might be used to define iterators, and we have at least 4: Inorder, Preorder, Postorder, and Levelorder. We will use all of these defined as external or "ADT-based" iterator classes. The native iterator class will be thread-based and have the advantage over stack-based Inorderiterator in that it requires +O(1) memory and is very fast. Please be familiar with the chapter of tree iterators before diving deeper into this project.

Map implementations also present the issue of what it means to de-reference an iterator. Sometimes we want the key, sometimes the data, and sometimes both. The solution is to package the key,data in a single object called an entry. An Entry object is similar to a Pair, except: (1) the names of the data are key_ and data_ (rather than first_ and second_), and (2) the key_ is a constant, so that it can never be changed. Mimicking the terminology in the standard library, we name the internal type to be returned by a dereferenced iterator "ValueType".

The external/ADT iterator classes are supplied for this project.

Procedural Requirements

  1. The official development/testing/assessment environment is specified in the Course Organizer.

  2. Create and work within a separate subdirectory cop4530/proj5.

  3. Begin by copying all files in the directory LIB/proj5 into your proj5 directory. At this point you should see these files (at least) in your directory:

    deliverables.sh
    map_bst_threaded.start      # start for map_bst_threaded.h
    mapiter_threaded.start      # start for mapiter_threaded.h
    main_wb3.cpp                # 3rd time's a charm for wordbench
    fmap_bst.cpp                # functionality test harness for Map
    mmap_bst.cpp                # hammer tester
    rantable.cpp                # create test files to be loaded by fmap.x
    

    Then copy these relevant executables from LIB/area51/:

    fmap_bst_i.x
    mmap_bst_i.x
    wb3_i.x
    

  4. Finally, you may want to copy the slave file for simpler access. (This file should not be in your project directory under its library name, nor should you attempt to modify it.)

    cp ~cop4530p/LIB/tcpp/map_bst_threaded_tools.cpp ~/cop4530/proj5/map_bst_threaded_tools.info
    

  5. Create the deliverables

    map_bst_threaded.h
    mapiter_threaded.h
    wordbench3.h
    wordbench3.cpp
    makefile.wb3
    log.txt        
    

    satisfying the requirements and specifications below.

  6. Test thoroughly, using the area51 executables as benchmarks. (See Hints on testing.)

  7. Submit the assignment using the command submit.sh.

    Warning: Submit scripts do not work on the program and linprog servers. Use shell.cs.fsu.edu to submit assignments. If you do not receive the second confirmation with the contents of your assignment, there has been a malfunction.

Code Requirements and Specifications

  1. Design of the Map and Map Iterator classes is captured in the start files and discussed in the lecture notes. Most of the function implementations are omitted, and of course need to be supplied.

  2. You are required to TYPE the code into the implementing bodies - code should NOT be copy/pasted. Typing the code will help you understand both the design and the implementation details.

  3. The implementation should follow the binary search tree pattern with iterative (not recursive) implementation of the Get operation.

  4. Map_BST must implement all of the Associative Array and Table APIs.

  5. Map_BST must exhibit all characteristics of unimodal associative containers.

  6. Map_BST methods Get, Put, Retrieve, Erase, Insert, and Includes must have average-case runtime O(log n), where n is the size of the table.

  7. In general, behavior should match that of the benchmark programs in area51.

  8. Note that the runtime constraints make it infeasible to call SetAllThreads as part of the implementation of any of the Map operations, except for those that copy the whole table - copy constructor and assignment operator.

  9. The only difference between Wordbench2 and Wordbench3 is that Wordbench2 uses OAA<String,size_t> and Wordbench3 uses Map_Threaded<String,size_t>, plus Wordbench3 adds a way to present the tree node height distribution to the user, for visual unspection of the search efficiency.

  10. You will have to re-implement WriteReport using a standard traversal of the underlying Map object to replace the clunky Display method of OAA. This is similar to what you did for the original WordBench.

  11. Wordbench3 must use fsu::Map_BST and behave in a manner identical to your Wordbench2, except with the added "ShowAnalysis" feature. ShowAnalysis is implemented with this code in wordbench.cpp:

    void WordBench::ShowAnalysis () const
    {
      fsu::Analysis(frequency_, std::cout, 15);
    }
    

    Analysis is a stand-alone function template supplied in map_bst_threaded_tools.cpp. The idea is to provide a user of wordbench with a way to see how efficient the map is for their particular word files.

Hints

/*
    map_bst_threaded.start

    <start by completing basic file header documentation!>

*/

#ifndef _MAP_BST_THREADED_H
#define _MAP_BST_THREADED_H

#include <cstddef>     // size_t
#include <cstdint>     // uint8_t
#include <iostream>
#include <iomanip>
#include <compare.h>   // LessThan
#include <queue.h>     // used in Dump()
#include <mapiter_adt.h>
#include <mapiter_threaded.h>

namespace fsu
{
  template < typename K , typename D , class P >
  class Map_BST;

  template < typename K , typename D, class P = fsu::LessThan<K> >
  class Map_BST
  {
  public:

    // family ties
    friend class ConstThreadedMapIterator < fsu::Map_BST<K,D,P> >;
    friend class ThreadedMapIterator      < fsu::Map_BST<K,D,P> >;
    friend class ConstInorderMapIterator  < fsu::Map_BST<K,D,P> >;
    friend class InorderMapIterator       < fsu::Map_BST<K,D,P> >;
    friend class PreorderMapIterator      < fsu::Map_BST<K,D,P> >;
    friend class PostorderMapIterator     < fsu::Map_BST<K,D,P> >;
    friend class LevelorderMapIterator    < fsu::Map_BST<K,D,P> >;

    // terminology support
    typedef K                                            KeyType;
    typedef D                                            DataType;
    typedef P                                            PredicateType;
    typedef typename fsu::Entry <K,D>                    ValueType; // type returned by iterator operator*
    typedef ThreadedMapIterator   < Map_BST <K,D,P> >    Iterator;  // native iterator
    typedef ConstThreadedMapIterator   < Map_BST <K,D,P> >    ConstIterator; // native constiterator
    typedef PreorderMapIterator   < Map_BST <K,D,P> >    PreorderIterator;   // stack-based
    typedef InorderMapIterator    < Map_BST <K,D,P> >    InorderIterator;    // stack-based
    typedef ConstInorderMapIterator    < Map_BST <K,D,P> >    ConstInorderIterator;     // stack-based
    typedef PostorderMapIterator  < Map_BST <K,D,P> >    PostorderIterator;  // stack-based
    typedef LevelorderMapIterator < Map_BST <K,D,P> >    LevelorderIterator; // queue-based

    // native iterator support (native = threaded)
    Iterator      Begin  ();
    Iterator      End    ();
    Iterator      rBegin ();
    Iterator      rEnd   ();
    ConstIterator Begin  () const;
    ConstIterator End    () const;
    ConstIterator rBegin () const;
    ConstIterator rEnd   () const;

    // external ADT iterators
    LevelorderIterator BeginLevelorder  () const;
    LevelorderIterator EndLevelorder    () const;

    InorderIterator BeginInorder        ();
    InorderIterator EndInorder          ();
    InorderIterator rBeginInorder       ();
    InorderIterator rEndInorder         ();

    ConstInorderIterator BeginInorder   () const;
    ConstInorderIterator EndInorder     () const;
    ConstInorderIterator rBeginInorder  () const;
    ConstInorderIterator rEndInorder    () const;

    PreorderIterator BeginPreorder      () const;
    PreorderIterator EndPreorder        () const;
    PreorderIterator rBeginPreorder     () const;
    PreorderIterator rEndPreorder       () const;

    PostorderIterator BeginPostorder    () const;
    PostorderIterator EndPostorder      () const;
    PostorderIterator rBeginPostorder   () const;
    PostorderIterator rEndPostorder     () const;

    // structural iterator support
    InorderIterator BeginStructuralInorder () const;

    // proper type
             Map_BST  ();
    explicit Map_BST  (P p);
             Map_BST  (const Map_BST& map);
             ~Map_BST ();
    Map_BST& operator=(const Map_BST& map);

    // associative array API
    D&        Get         (const KeyType& k);
    void      Put         (const KeyType& k , const DataType& d);
    bool      Retrieve    (const KeyType& k, DataType& d) const;

    DataType& operator [] (const KeyType& k);

    // table API
    Iterator       Includes (const KeyType& k);
    ConstIterator  Includes (const KeyType& k) const;
    void           Insert   (const KeyType& k , const DataType& d);
    void           Insert   (Iterator i, const K& k, const D& d);

    // ordered table 
    Iterator       LowerBound (const K& k) const;
    Iterator       UpperBound (const K& k) const;

    // common remove operations
    void   Erase    (const KeyType& k);
    void   Clear    ();
    void   Rehash   ();

    // size operations - implemented in-line with calls to private recursive methods
    bool   Empty    () const { return root_ == nullptr; } // doesn't cover case
                                                          // of "nothing but
                                                          // tombstones"
    size_t Size     () const { return RSize(root_); }     // counts alive nodes
    size_t NumNodes () const { return RNumNodes(root_); } // counts all nodes
    int    Height   () const { return RHeight(root_); }

    // development support
    void   DumpBW   (std::ostream& os) const;
    void   Dump     (std::ostream& os) const;
    void   Dump     (std::ostream& os, int kw) const;
    void   Dump     (std::ostream& os, int kw, char fill) const;
    void   DepthDistribution (std::ostream& os, size_t skip) const;

    // diagnoistics
    bool   CheckBST        (bool verboseFlag) const; // 0,1
    bool   CheckAllThreads (bool verboseFlag) const;
    bool   CheckStructure  (bool  verboseFlag) const { return CheckBST (verboseFlag) && CheckAllThreads(verboseFlag); } // generic  name

  private: // types

    enum Flags
    {

    };

    struct Node
    {
      // KeyType       key_;
      // DataType      data_;
      fsu::Entry<KeyType,DataType>    value_;
      Node *        lchild_,
           *        rchild_;
      uint8_t       flags_;
      // Flags         flags_;

      Node (const KeyType& k, const DataType& d, Flags flags)
        : value_(k,d), lchild_(nullptr), rchild_(nullptr), flags_(flags)
      {}

      // support for color management
      bool IsRed    () const { } // needs implementatiom
      bool IsBlack  () const { } // needs implementatiom
      void SetRed   ()       { } // needs implementatiom
      void SetBlack ()       { } // needs implementatiom

      // support for graveyard management
      bool IsDead   () const { } // needs implementatiom
      bool IsAlive  () const { } // needs implementatiom
      void SetDead  ()       { } // needs implementatiom
      void SetAlive ()       { } // needs implementatiom

      // support for search
      bool HasLeftChild       () const { return (lchild_ != nullptr) && !(IsLeftThreaded()); }
      bool HasRightChild      () const { return (rchild_ != nullptr) && !(IsRightThreaded()); }

      // support for threaded management   
      bool IsLeftThreaded     () const  { return 0 != (LEFT_THREAD & flags_); }
      bool IsRightThreaded    () const  { return 0 != (RIGHT_THREAD & flags_); }
      void SetLeftThread      (Node* n) { lchild_ = n; flags_ |= LEFT_THREAD; }
      void SetRightThread     (Node* n) { rchild_ = n; flags_ |= RIGHT_THREAD; }
      void SetLeftChild       (Node* n) { lchild_ = n; flags_ &= ~LEFT_THREAD; }
      void SetRightChild      (Node* n) { rchild_ = n; flags_ &= ~RIGHT_THREAD; }

      static const char* ColorMap (uint8_t flags)
      {
        flags &= 0x03; // last 2 bits only
        switch(flags)
        {
          case 0x00: return ANSI_BOLD_BLUE;        // bits 00 = !RED |  ALIVE 
          case 0x01: return ANSI_BOLD_BLUE_SHADED; // bits 01 = !RED | !ALIVE
          case 0x02: return ANSI_BOLD_RED;         // bits 10 =  RED |  ALIVE
          case 0x03: return ANSI_BOLD_RED_SHADED;  // bits 11 =  RED | !ALIVE
          default: return "unknown color";   // unknown flags
        }
      }

      static char BWMap (uint8_t flags)
      {
        switch(flags)
        {
          case 0x00: return 'B'; // bits 00 black alive
          case 0x01: return 'b'; // bits 01 black dead
          case 0x02: return 'R'; // bits 10 red alive
          case 0x03: return 'r'; // bits 11 red dead
          default:   return 'U'; // unknown flags
        }
      }

      // node dump - may be used during development
      void Dump (std::ostream& os = std::cout) const
      {
        os << "  Node data:\n"
           << "    value:          " << value_  << '\n'
           << "    color:          " << (size_t)IsRed() << '\n'
           << "    alive:          " << (size_t)IsAlive() << '\n'
           << "    left_threaded:  " << (size_t)IsLeftThreaded() << '\n'
           << "    right_threaded: " << (size_t)IsRightThreaded() << '\n';
        os << "    lchild:         ";
        if (lchild_ != nullptr)
        {
          if (IsLeftThreaded())
            os << lchild_->value_  << " (predecessor)\n";
          else
            os << lchild_->value_  << " (left child)\n";
        }
        else
          os << "NULL\n";
        os << "    rchild:         ";
        if (rchild_ != nullptr)
        {
          if (IsRightThreaded())
            os << rchild_->value_  << " (succecessor)\n";
          else
            os << rchild_->value_  << " (right child)\n";
        }
        else
          os << "NULL\n";
        os << std::flush;
      }
    }; // end struct Node

  private: // class data
    Node *         root_;
    PredicateType  pred_;

  private: // methods
    void SetAllThreads ();

    static Node * NewNode     (const K& k, const D& d, Flags flags = ZERO);
    static void   RRelease    (Node* n); // deletes all descendants of n
    static Node * RClone      (const Node* n); // returns deep copy of n
    static size_t RSize       (Node * n);
    static size_t RNumNodes   (Node * n);
    static int    RHeight     (Node * n);

  }; // end class Map_BST<>

  // define equality using class iterator type

  template < typename K , typename D , class P > 
  bool operator == (const Map_BST<K,D,P>& map1, const Map_BST<K,D,P>& map2)
  {
  }

  template < typename K , typename D , class P > 
  bool operator != (const Map_BST<K,D,P>& b1, const Map_BST<K,D,P>& b2)
  {
  }

  // Iterator support methods
  
  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::Iterator Map_BST<K,D,P>::Begin()
  {
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::Iterator Map_BST<K,D,P>::End()
  {
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::Iterator Map_BST<K,D,P>::rBegin()
  {
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::Iterator Map_BST<K,D,P>::rEnd()
  {
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::ConstIterator Map_BST<K,D,P>::Begin() const
  {
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::ConstIterator Map_BST<K,D,P>::End() const
  {
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::ConstIterator Map_BST<K,D,P>::rBegin() const
  {
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::ConstIterator Map_BST<K,D,P>::rEnd() const
  {
  }

  // the Iterator locator methods 

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::Iterator Map_BST<K,D,P>::Includes ( const K& k )
  {
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::ConstIterator Map_BST<K,D,P>::Includes ( const K& k ) const
  {
  }

  template < typename K , typename D , class P >
  void Map_BST<K,D,P>::Put (const K& k, const D& d)
  {
  }

  template < typename K , typename D , class P >
  void Map_BST<K,D,P>::Insert (const K& k, const D& d)
  {
  }

  template < typename K , typename D , class P >
  D& Map_BST<K,D,P>::Get (const K& k)
  {
  }

  template < typename K , typename D , class P >
  bool Map_BST<K,D,P>::Retrieve (const K& k, D& d) const
  {
  }

  template < typename K , typename D , class P >
  void Map_BST<K,D,P>::Erase ( const K& k )
  {
  }

  template < typename K , typename D , class P >
  void Map_BST<K,D,P>::Clear()
  {
  }

  // recursive support methods
  template < typename K , typename D , class P >
  size_t Map_BST<K,D,P>::RSize(Node * n)
  {
  }

  template < typename K , typename D , class P >
  size_t Map_BST<K,D,P>::RNumNodes(Node * n)
  {
  }

  template < typename K , typename D , class P >
  int Map_BST<K,D,P>::RHeight(Node * n)
  {
  }

  template < typename K , typename D , class P >
  void Map_BST<K,D,P>::RRelease(Node* n)
  // post:  all descendants of n have been deleted
  {
  }

  /***********************************************/
  /* below here all implementations are provided */
  /***********************************************/

  template < typename K , typename D , class P >
  void Map_BST<K,D,P>::Insert (Iterator i, const K& k, const D& d)
  {
    if (i.Valid() && k == (*i).value_.key_)
    {
      i.node_->value_.data_ = d;
      i.node_->SetAlive();
      return;
    }
    Map_BST<K,D,P>::Insert(k,d);
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::Iterator Map_BST<K,D,P>::LowerBound ( const K& k ) const
  {
    if (this->root_ == nullptr)
      return End();
    Iterator l = End();
    Node * n = this->root_;
    bool finished = 0;
    while (! finished)
    {
      if (!this->pred_(n->value_.key_,k)) // t <= n
      {
        l.node_ = n;
        if (n->HasLeftChild())
          n = n->lchild_;
        else
          finished = 1;
      }
      else // t > n
      {
        if (n->HasRightChild())
          n = n->rchild_;
        else
          finished = 1;
      }
    }
    // take care of dead node case
    if (l.Valid() && l.node_->IsDead())
      ++l;
    return l;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::Iterator Map_BST<K,D,P>::UpperBound ( const K& k ) const
  {
    if (this->root_ == nullptr)
      return End();
    Iterator u = End();
    Node * n = this->root_;
    bool finished = 0;
    while (! finished)
    {
      if (this->pred_(k,n->value_.key_)) // t < n
      {
        u.node_ = n;
        if (n->HasLeftChild())
          n = n->lchild_;
        else
          finished = 1;
      }
      else // t >= n
      {
        if (n->HasRightChild())
          n = n->rchild_;
        else
          finished = 1;
      }
    }
    // take care of dead node case
    if (u.Valid() && u.node_->IsDead())
      ++u;
    return u;
  }

  template < typename K , typename D , class P >
  void Map_BST<K,D,P>::Rehash()
  // restructure with no tombstones
  {
    Map_BST<K,D,P> newtree;
    for (PreorderIterator i = this->BeginPreorder(); i != this->EndPreorder(); ++i)
    // for (LevelorderIterator i = this->BeginLevelorder(); i != this->EndLevelorder(); ++i)
    {
      newtree.Insert((*i).key_, (*i).data_);
    }
    fsu::Swap(this->root_,newtree.root_);
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::Node* Map_BST<K,D,P>::RClone(const Map_BST<K,D,P>::Node* n)
  // returns a pointer to a deep copy of n
  // parentless version
  // does NOT set threads!
  {

    if (n == nullptr)
      return nullptr;
    Node* newN = NewNode (n->value_.key_, n->value_.data_, (Flags)n->flags_);
    if (n->HasLeftChild())
      newN->lchild_ = RClone(n->lchild_);
    else
      newN->lchild_ = nullptr;
    if (n->HasRightChild())
      newN->rchild_ = RClone(n->rchild_);
    else
      newN->rchild_ = nullptr;
    return newN;
  } // end RClone() */

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::Node * Map_BST<K,D,P>::NewNode(const K& k, const D& d, Flags flags) 
  {
    Node * nPtr = new(std::nothrow) Node(k,d,flags);
    if (nPtr == nullptr)
    {
      std::cerr << "** Map_BST memory allocation failure\n";
      // handle exception in-class here
    }
    return nPtr;
  }

  // proper type
  
  template < typename K , typename D , class P >
  Map_BST<K,D,P>::Map_BST  () : root_(nullptr), pred_()
  {}

  template < typename K , typename D , class P >
  Map_BST<K,D,P>::Map_BST  (P p) : root_(nullptr), pred_(p)
  {}

  template < typename K , typename D , class P >
  Map_BST<K,D,P>::~Map_BST ()
  {
    this->Clear();
  }

  template < typename K , typename D , class P >
  Map_BST<K,D,P>::Map_BST( const Map_BST<K,D,P>& tree )
  {
    root_ = RClone(tree.root_);
    this->SetAllThreads();
  }

  template < typename K , typename D , class P >
  Map_BST<K,D,P>& Map_BST<K,D,P>::operator=( const Map_BST<K,D,P>& that )
  {
    if (this != &that)
    {
      Clear();
      root_ = RClone(that.root_);
      this->SetAllThreads();
    }
    return *this;
  }

  // "Structural" iteration goes over the tree (not the represented set)
  // stopping at ALL nodes, dead or alive.
  // A structural traversal is used by the SetAllThreads method, a critical step
  // in copying a threaded BST.
  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::InorderIterator Map_BST<K,D,P>::BeginStructuralInorder () const
  {
    InorderIterator i;
    i.sInit(root_);
    return i;
  }

  // protected helper method prototyped in base class
  template < typename K , typename D , class P >
  void Map_BST<K,D,P>::SetAllThreads ()
  {
    // fsu::Debug("SetAllThreads");
    InorderIterator i = BeginStructuralInorder();
    if (i == EndInorder()) return;
    Node * n1, * n2;
    n1 = i.stk_.Top();
    n1->SetLeftThread(nullptr);
    i.Increment();
    while (i != EndInorder())
    {
      n2 = i.stk_.Top();
      if (!n1->HasRightChild())
      {
        n1->SetRightThread(n2);
      }
      if (!n2->HasLeftChild())
      {
        n2->SetLeftThread(n1);
      }
      n1 = n2;
      i.Increment();
    }
    n1->SetRightThread(nullptr);
  }

  // ADT-based iterator support

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::InorderIterator Map_BST<K,D,P>::BeginInorder()
  {
    InorderIterator i;
    i.Init(this->root_);
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::InorderIterator Map_BST<K,D,P>::EndInorder()
  {
    InorderIterator i;
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::InorderIterator Map_BST<K,D,P>::rBeginInorder()
  {
    InorderIterator i;
    i.rInit(this->root_);
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::InorderIterator Map_BST<K,D,P>::rEndInorder()
  {
    InorderIterator i;
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::ConstInorderIterator Map_BST<K,D,P>::BeginInorder() const
  {
    ConstInorderIterator i;
    i.Init(this->root_);
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::ConstInorderIterator Map_BST<K,D,P>::EndInorder() const
  {
    ConstInorderIterator i;
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::ConstInorderIterator Map_BST<K,D,P>::rBeginInorder() const
  {
    ConstInorderIterator i;
    i.rInit(this->root_);
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::ConstInorderIterator Map_BST<K,D,P>::rEndInorder() const
  {
    ConstInorderIterator i;
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::LevelorderIterator Map_BST<K,D,P>::BeginLevelorder() const
  {
    LevelorderIterator i;
    i.Init(this->root_);
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::LevelorderIterator Map_BST<K,D,P>::EndLevelorder() const
  {
    LevelorderIterator i;
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::PreorderIterator Map_BST<K,D,P>::BeginPreorder() const
  {
    PreorderIterator i;
    i.Init(this->root_);
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::PreorderIterator Map_BST<K,D,P>::EndPreorder() const
  {
    PreorderIterator i;
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::PreorderIterator Map_BST<K,D,P>::rBeginPreorder() const
  {
    PreorderIterator i;
    i.rInit(this->root_);
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::PreorderIterator Map_BST<K,D,P>::rEndPreorder() const
  {
    PreorderIterator i;
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::PostorderIterator Map_BST<K,D,P>::BeginPostorder() const
  {
    PostorderIterator i;
    i.Init(this->root_);
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::PostorderIterator Map_BST<K,D,P>::EndPostorder() const
  {
    PostorderIterator i;
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::PostorderIterator Map_BST<K,D,P>::rBeginPostorder() const
  {
    PostorderIterator i;
    i.rInit(this->root_);
    return i;
  }

  template < typename K , typename D , class P >
  typename Map_BST<K,D,P>::PostorderIterator Map_BST<K,D,P>::rEndPostorder() const
  {
    PostorderIterator i;
    return i;
  }

#include <map_bst_threaded_tools.cpp>

} // namespace fsu 

#endif

/*
    mapiter_threaded.start

    <make your bed first thing!>

*/

#include <cstddef>     // size_t
#include <cstdint>     // uint8_t
#include <ansicodes.h>
#include <iostream>
#include <iomanip>

#ifndef _MAPITER_THREADED_H
#define _MAPITER_THREADED_H

namespace fsu
{

  template < class C >
  class ConstThreadedMapIterator;   // patterns: ConstIterator, BidirectionalIterator

  template < class C >
  class ThreadedMapIterator;        // patterns: Iterator, BidirectionalIterator

  /*****************************************************/
  /*        class ConstThreadedMapIterator < C >       */
  /*****************************************************/

  template < class C >
  class ConstThreadedMapIterator // a ConstIterator pattern
  {
  protected:
    friend   C;
    typename C::Node* node_;

  public:
    // terminology support
    typedef typename C::ValueType        ValueType;
    typedef typename C::Node             Node;
    typedef ConstThreadedMapIterator<C>  ConstIterator;
    typedef ThreadedMapIterator<C>       Iterator;

    // constructors
             ConstThreadedMapIterator  ();
    virtual  ~ConstThreadedMapIterator ();
             ConstThreadedMapIterator  (Node* n);    // type converter
             ConstThreadedMapIterator  (const ConstThreadedMapIterator& i); // copy ctor

    // information/access
    bool  Valid   () const; // cursor is valid element

    // various operators
    bool                     operator == (const ConstThreadedMapIterator& i2) const;
    bool                     operator != (const ConstThreadedMapIterator& i2) const;
    const ValueType&         operator *  () const; // const version
    // ValueType&               operator *  ();       // non-const version
    ConstThreadedMapIterator<C>&  operator =  (const ConstThreadedMapIterator& i);
    ConstThreadedMapIterator<C>&  operator ++ ();    // prefix
    ConstThreadedMapIterator<C>   operator ++ (int); // postfix
    ConstThreadedMapIterator<C>&  operator -- ();    // prefix
    ConstThreadedMapIterator<C>   operator -- (int); // postfix

    // developers helper
    void Dump    ( std::ostream& os = std::cout , char = '\0' );

  private:
    void Init        (Node*);   
    void rInit       (Node*);
    void Increment   ();  // moves to next inorder node
    void Decrement   ();  // moves to previous inorder node

  };

  // protected increment/decrement
  template < class C >
  void ConstThreadedMapIterator<C>::Init(Node* n)
  {
  }

  template < class C >
  void ConstThreadedMapIterator<C>::rInit(Node* n)
  {
  }

  template < class C >
  void ConstThreadedMapIterator<C>::Increment ()
  {
  }

  template < class C >
  void ConstThreadedMapIterator<C>::Decrement ()
  {
  }

  template < class C >
  bool ConstThreadedMapIterator<C>::Valid() const
  {
  }

  // other operators

  template < class C >
  ConstThreadedMapIterator<C> & ConstThreadedMapIterator<C>::operator ++()
  {
  }

  template < class C >
  ConstThreadedMapIterator<C>   ConstThreadedMapIterator<C>::operator ++(int)
  {
  }

  template < class C >
  ConstThreadedMapIterator<C> & ConstThreadedMapIterator<C>::operator --()
  {
  }

  template < class C >
  ConstThreadedMapIterator<C>   ConstThreadedMapIterator<C>::operator --(int)
  {
  }

  template < class C >
  const typename C::ValueType& ConstThreadedMapIterator<C>::operator *() const
  {
  }

  template < class C >
  bool ConstThreadedMapIterator<C>::operator == (const ConstThreadedMapIterator<C>& i2) const
  {
  }

  template < class C >
  bool ConstThreadedMapIterator<C>::operator != (const ConstThreadedMapIterator<C>& i2) const
  {
  }

  /*****************************************************/
  /*        class ThreadedMapIterator < C >             */
  /*****************************************************/

  template < class C >
  class ThreadedMapIterator : public ConstThreadedMapIterator <C>
  {
  private:
    friend   C;
    // typename C::Node* node_;

  public:
    // terminology support
    typedef typename C::ValueType    ValueType;
    typedef typename C::Node         Node;
    typedef ThreadedMapIterator<C>   ConstIterator;
    typedef ThreadedMapIterator<C>   Iterator;

    // constructors
             ThreadedMapIterator  ();
    virtual  ~ThreadedMapIterator ();
             ThreadedMapIterator  (Node* n);    // type converter
             ThreadedMapIterator  (const ThreadedMapIterator& i); // copy ctor

    // information/access
    // bool  Valid   () const; // cursor is valid element

    // various operators
    bool                     operator == (const ThreadedMapIterator& i2) const;
    bool                     operator != (const ThreadedMapIterator& i2) const;
    const ValueType&         operator *  () const; // const version
    ValueType&               operator *  ();       // non-const version
    ThreadedMapIterator<C>&  operator =  (const ThreadedMapIterator& i);
    ThreadedMapIterator<C>&  operator ++ ();    // prefix
    ThreadedMapIterator<C>   operator ++ (int); // postfix
    ThreadedMapIterator<C>&  operator -- ();    // prefix
    ThreadedMapIterator<C>   operator -- (int); // postfix

    // developers helper
    // void Dump    ( std::ostream& os = std::cout , char = '\0' );

  private:
    // void Init        (Node*);   
    // void rInit       (Node*);
    // void Increment   ();  // moves to next inorder node
    // void Decrement   ();  // moves to previous inorder node

  };

  template < class C >
  bool ThreadedMapIterator<C>::operator == (const ThreadedMapIterator<C>& i2) const
  {
  }

  template < class C >
  bool ThreadedMapIterator<C>::operator != (const ThreadedMapIterator<C>& i2) const
  {
  }

  /**************************************************/
  /* below here everything is implemented correctly */ 
  /**************************************************/

  // proper types

  template < class C >
  ConstThreadedMapIterator<C>::ConstThreadedMapIterator ()  :  node_()
  {}

  template < class C >
  ConstThreadedMapIterator<C>::~ConstThreadedMapIterator () 
  {}

  template < class C >
  ConstThreadedMapIterator<C>::ConstThreadedMapIterator (const ConstThreadedMapIterator<C>& i)
    :  node_(i.node_)
  {}

  template < class C >
  ConstThreadedMapIterator<C>::ConstThreadedMapIterator (Node * n)
    :  node_(n)
  {}

  template < class C >
  ConstThreadedMapIterator<C> & ConstThreadedMapIterator<C>::operator =  (const ConstThreadedMapIterator<C>& i)
  {
    node_ = i.node_;
    return *this;
  }

  template < class C >
  ThreadedMapIterator<C>::ThreadedMapIterator ()  :  ConstThreadedMapIterator<C>()
  {}

  template < class C >
  ThreadedMapIterator<C>::~ThreadedMapIterator () 
  {}

  template < class C >
  ThreadedMapIterator<C>::ThreadedMapIterator (const ThreadedMapIterator<C>& i)
    :  ConstThreadedMapIterator<C>(i)
  {}

  template < class C >
  ThreadedMapIterator<C>::ThreadedMapIterator (Node * n)
    :  ConstThreadedMapIterator<C>(n)
  {}

  // derived class operators implemented with calls to base class versions

  template < class C >
  ThreadedMapIterator<C> & ThreadedMapIterator<C>::operator =  (const ThreadedMapIterator<C>& i)
  {
    ConstThreadedMapIterator<C>::operator=(i);
    return *this;
  }

  template < class C >
  ThreadedMapIterator<C> & ThreadedMapIterator<C>::operator ++()
  {
    ConstThreadedMapIterator<C>::operator++();
    return *this;
  }

  template < class C >
  ThreadedMapIterator<C>   ThreadedMapIterator<C>::operator ++(int)
  {
    ThreadedMapIterator<C> i = *this;
    operator ++();
    return i;
  }

  template < class C >
  ThreadedMapIterator<C> & ThreadedMapIterator<C>::operator --()
  {
    ConstThreadedMapIterator<C>::operator--();
    return *this;
  }

  template < class C >
  ThreadedMapIterator<C>   ThreadedMapIterator<C>::operator --(int)
  {
    ThreadedMapIterator<C> i = *this;
    operator --();
    return i;
  }

  template < class C >
  const typename C::ValueType& ThreadedMapIterator<C>::operator *() const
  {
    return this->node_->value_;
  }

  template < class C >
  typename C::ValueType& ThreadedMapIterator<C>::operator *()
  {
    return this->node_->value_;
  }

  // the iterator dump method is completely implemented here:

  template < class C >
  void ConstThreadedMapIterator<C>::Dump(std::ostream& os , char)
  {
    os << "node: " << node_->value_ << " , ";
    if (node_->IsRightThreaded())
    {
      if (node_->rchild_ == nullptr)
        os << "++: null , ";
      else
        os << "++: " << node_->rchild_->value_ << " , ";
    }
    else
    {
      if (node_->rchild_ == nullptr)
        os << "rchild: null , ";
      else
        os << "rchild: " << node_->rchild_->value_ << " , ";
    }
    if (node_->IsLeftThreaded())
    {
      if (node_->lchild_ == nullptr)
        os << "--: null\n";
      else
        os << "--: " << node_->lchild_->value_ << '\n';
    }
    else
    {
      if (node_->lchild_ == nullptr)
        os << "lchild: null\n";
      else
        os << "lchild: " << node_->lchild_->value_ << '\n';
    }
  }
    
} // namespace fsu 

#endif