/***************************************** * UW User ID: uwuserid * Submitted for ECE 250 * Semester of Submission: (Winter|Spring|Fall) 20NN * * By submitting this file, I affirm that * I am the author of all modifications to * the provided code. *****************************************/ #ifndef RPOVDGBQN9TIEO3P #define RPOVDGBQN9TIEO3P #include "Exception.h" #include "ece250.h" #include template class Search_tree { public: class Iterator; private: class Node { public: Type node_value; int tree_height; // The left and right sub-trees Node *left_tree; Node *right_tree; // Hint as to how you can create your iterator // Point to the previous and next nodes in linear order Node *previous_node; Node *next_node; // Member functions Node( Type const & = Type() ); void update_height(); int height() const; bool is_leaf() const; Node *front(); Node *back(); Node *find( Type const &obj ); void clear(); bool insert( Type const &obj, Node *&to_this ); bool erase( Type const &obj, Node *&to_this ); }; Node *root_node; int tree_size; // Hint as to how to start your linked list of the nodes in order Node *front_sentinel; Node *back_sentinel; public: class Iterator { private: Search_tree *containing_tree; Node *current_node; bool is_end; // The constructor is private so that only the search tree can create an iterator Iterator( Search_tree *tree, Node *starting_node ); public: // DO NOT CHANGE THE SIGNATURES FOR ANY OF THESE Type operator*() const; Iterator &operator++(); Iterator &operator--(); bool operator==( Iterator const &rhs ) const; bool operator!=( Iterator const &rhs ) const; // Make the search tree a friend so that it can call the constructor friend class Search_tree; }; // DO NOT CHANGE THE SIGNATURES FOR ANY OF THESE Search_tree(); ~Search_tree(); bool empty() const; int size() const; int height() const; Type front() const; Type back() const; Iterator begin(); Iterator end(); Iterator rbegin(); Iterator rend(); Iterator find( Type const & ); void clear(); bool insert( Type const & ); bool erase( Type const & ); // Friends template friend std::ostream &operator<<( std::ostream &, Search_tree const & ); }; ////////////////////////////////////////////////////////////////////// // Search Tree Public Member Functions // ////////////////////////////////////////////////////////////////////// // The initialization of the front and back sentinels is a hint template Search_tree::Search_tree(): root_node( nullptr ), tree_size( 0 ), front_sentinel( new Search_tree::Node( Type() ) ), back_sentinel( new Search_tree::Node( Type() ) ) { front_sentinel->next_node = back_sentinel; back_sentinel->previous_node = front_sentinel; } template Search_tree::~Search_tree() { clear(); // might as well use it... delete front_sentinel; delete back_sentinel; } template bool Search_tree::empty() const { return ( root_node == nullptr ); } template int Search_tree::size() const { return tree_size; } template int Search_tree::height() const { return root_node->height(); } template Type Search_tree::front() const { if ( empty() ) { throw underflow(); } return root_node->front()->node_value; } template Type Search_tree::back() const { if ( empty() ) { throw underflow(); } return root_node->back()->node_value; } template typename Search_tree::Iterator Search_tree::begin() { return empty() ? Iterator( this, back_sentinel ) : Iterator( this, root_node->front() ); } template typename Search_tree::Iterator Search_tree::end() { return Iterator( this, back_sentinel ); } template typename Search_tree::Iterator Search_tree::rbegin() { return empty() ? Iterator( this, front_sentinel ) : Iterator( this, root_node->back() ); } template typename Search_tree::Iterator Search_tree::rend() { return Iterator( this, front_sentinel ); } template typename Search_tree::Iterator Search_tree::find( Type const &obj ) { if ( empty() ) { return Iterator( this, back_sentinel ); } typename Search_tree::Node *search_result = root_node->find( obj ); if ( search_result == nullptr ) { return Iterator( this, back_sentinel ); } else { return Iterator( this, search_result ); } } template void Search_tree::clear() { if ( !empty() ) { root_node->clear(); root_node = nullptr; tree_size = 0; } // Reinitialize the sentinels front_sentinel->next_node = back_sentinel; back_sentinel->previous_node = front_sentinel; } template bool Search_tree::insert( Type const &obj ) { if ( empty() ) { root_node = new Search_tree::Node( obj ); tree_size = 1; return true; } else if ( root_node->insert( obj, root_node ) ) { ++tree_size; return true; } else { return false; } } template bool Search_tree::erase( Type const &obj ) { if ( !empty() && root_node->erase( obj, root_node ) ) { --tree_size; return true; } else { return false; } } ////////////////////////////////////////////////////////////////////// // Node Public Member Functions // ////////////////////////////////////////////////////////////////////// template Search_tree::Node::Node( Type const &obj ): node_value( obj ), left_tree( nullptr ), right_tree( nullptr ), next_node( nullptr ), previous_node( nullptr ), tree_height( 0 ) { // does nothing } template void Search_tree::Node::update_height() { tree_height = std::max( left_tree->height(), right_tree->height() ) + 1; } template int Search_tree::Node::height() const { return ( this == nullptr ) ? -1 : tree_height; } // Return true if the current node is a leaf node, false otherwise template bool Search_tree::Node::is_leaf() const { return ( (left_tree == nullptr) && (right_tree == nullptr) ); } // Return a pointer to the front node template typename Search_tree::Node *Search_tree::Node::front() { return ( left_tree == nullptr ) ? this : left_tree->front(); } // Return a pointer to the back node template typename Search_tree::Node *Search_tree::Node::back() { return ( right_tree == nullptr ) ? this : right_tree->back(); } template typename Search_tree::Node *Search_tree::Node::find( Type const &obj ) { if ( obj == node_value ) { return this; } else if ( obj < node_value ) { return (left_tree == nullptr) ? nullptr : left_tree->find( obj ); } else { return ( right_tree == nullptr ) ? nullptr : right_tree->find( obj ); } } // Recursively clear the tree template void Search_tree::Node::clear() { if ( left_tree != nullptr ) { left_tree->clear(); } if ( right_tree != nullptr ) { right_tree->clear(); } delete this; } template bool Search_tree::Node::insert( Type const &obj, Search_tree::Node *&to_this ) { if ( obj < node_value ) { if ( left_tree == nullptr ) { left_tree = new Search_tree::Node( obj ); update_height(); return true; } else { if ( left_tree->insert( obj, left_tree ) ) { update_height(); return true; } else { return false; } } } else if ( obj > node_value ) { if ( right_tree == nullptr ) { right_tree = new Search_tree::Node( obj ); update_height(); return true; } else { if ( right_tree->insert( obj, right_tree ) ) { update_height(); return true; } else { return false; } } } else { return false; } } template bool Search_tree::Node::erase( Type const &obj, Search_tree::Node *&to_this ) { if ( obj < node_value ) { if ( left_tree == nullptr ) { return false; } else { if ( left_tree->erase( obj, left_tree ) ) { update_height(); return true; } return false; } } else if ( obj > node_value ) { if ( right_tree == nullptr ) { return false; } else { if ( right_tree->erase( obj, right_tree ) ) { update_height(); return true; } return false; } } else { assert( obj == node_value ); if ( is_leaf() ) { to_this = nullptr; delete this; } else if ( left_tree == nullptr ) { to_this = right_tree; delete this; } else if ( right_tree == nullptr ) { to_this = left_tree; delete this; } else { node_value = right_tree->front()->node_value; right_tree->erase( node_value, right_tree ); update_height(); } return true; } } ////////////////////////////////////////////////////////////////////// // Iterator Private Constructor // ////////////////////////////////////////////////////////////////////// template Search_tree::Iterator::Iterator( Search_tree *tree, typename Search_tree::Node *starting_node ): containing_tree( tree ), current_node( starting_node ) { // This is done for you... // Does nothing... } ////////////////////////////////////////////////////////////////////// // Iterator Public Member Functions // ////////////////////////////////////////////////////////////////////// template Type Search_tree::Iterator::operator*() const { // This is done for you... return current_node->node_value; } template typename Search_tree::Iterator &Search_tree::Iterator::operator++() { // Update the current node to the node containing the next higher value // If we are already at end do nothing // Your implementation here, do not change the return value return *this; } template typename Search_tree::Iterator &Search_tree::Iterator::operator--() { // Update the current node to the node containing the next smaller value // If we are already at either rend, do nothing // Your implementation here, do not change the return value return *this; } template bool Search_tree::Iterator::operator==( typename Search_tree::Iterator const &rhs ) const { // This is done for you... return ( current_node == rhs.current_node ); } template bool Search_tree::Iterator::operator!=( typename Search_tree::Iterator const &rhs ) const { // This is done for you... return ( current_node != rhs.current_node ); } ////////////////////////////////////////////////////////////////////// // Friends // ////////////////////////////////////////////////////////////////////// // You can modify this function however you want: it will not be tested template std::ostream &operator<<( std::ostream &out, Search_tree const &list ) { out << "not yet implemented"; return out; } #endif