#include "../queue/queue.hpp" #include "../queue/vec/queuevec.hpp" #include "../queue/lst/queuelst.hpp" #include "../stack/stack.hpp" #include "../stack/lst/stacklst.hpp" #include "../stack/vec/stackvec.hpp" #include namespace lasd { /* ----- begin of class BinaryTree ----- */ /* ----- begin of struct Node ----- */ template bool BinaryTree::Node::operator==(const Node& toEvaluate) const noexcept{ return EqualNodes(*this, toEvaluate); } template bool BinaryTree::Node::operator!=(const Node& toEvaluate) const noexcept{ return !(*this == toEvaluate); } /* given two nodes, checks if the subtree is the same */ template bool BinaryTree::Node::EqualNodes(const Node& n1, const Node& n2) const{ if(n1.data == n2.data){ if( (n1.HasLeftChild() && !n2.HasLeftChild()) || (n1.HasRightChild() && !n2.HasRightChild()) ) return false; if(n1.HasLeftChild() && n1.HasRightChild()){ return( EqualNodes(n1.LeftChild(),n2.LeftChild()) && EqualNodes(n1.RightChild(),n2.RightChild())); } else if(n1.HasLeftChild() && !n1.HasRightChild()){ return( EqualNodes(n1.LeftChild(),n2.LeftChild())); } else if(!n1.HasLeftChild() && n1.HasRightChild()){ return( EqualNodes(n1.RightChild(),n2.RightChild())); } else{ //if leaf return true; } }else{ return false; } } template Data& BinaryTree::Node::Element(){ return this->data; } template const Data& BinaryTree::Node::Element() const{ return this->data; } /* ----- end of struct Node ----- */ template bool BinaryTree::operator==(const BinaryTree& tree) const noexcept{ if(size == tree.size){ if(size == 0) return true; else return (Root() == tree.Root()); }else{ return false; } } template bool BinaryTree::operator!=(const BinaryTree& toCompare) const noexcept{ return !(*this == toCompare); } /* ----- Map and fold functions ----- */ template void BinaryTree::MapPreOrder(const typename MappableContainer::MapFunctor function, void* par){ if(size == 0) return; MapPreOrder(function, par, &Root()); } template void BinaryTree::MapPostOrder(const typename MappableContainer::MapFunctor function, void* par){ if(size == 0) return; MapPostOrder(function, par, &Root()); } template void BinaryTree::MapInOrder(const typename MappableContainer::MapFunctor function, void* par){ if(size == 0) return; MapInOrder(function, par, &Root()); } template void BinaryTree::MapBreadth(const typename MappableContainer::MapFunctor function, void* par){ if(size == 0) return; MapBreadth(function, par, &Root()); } template void BinaryTree::FoldPreOrder(const typename FoldableContainer::FoldFunctor function, const void* par, void* acc) const{ if(size == 0) return; FoldPreOrder(function, par, acc, &Root()); } template void BinaryTree::FoldPostOrder(const typename FoldableContainer::FoldFunctor function, const void* par, void* acc) const{ if(size == 0) return; FoldPostOrder(function, par, acc, &Root()); } template void BinaryTree::FoldInOrder(const typename FoldableContainer::FoldFunctor function, const void* par, void* acc) const{ if(size == 0) return; FoldInOrder(function, par, acc, &Root()); } template void BinaryTree::FoldBreadth(const typename FoldableContainer::FoldFunctor function, const void* par, void* acc) const{ if(size == 0) return; FoldBreadth(function, par, acc, &Root()); } /* ----- Auxiliary map and fold functions ----- */ template void BinaryTree::MapPreOrder(const typename MappableContainer::MapFunctor function, void* par, Node* node){ if(node != nullptr){ function(node->Element(), par); if(node->HasLeftChild()){ MapPreOrder(function, par, &(node->LeftChild())); } if(node->HasRightChild()){ MapPreOrder(function, par, &(node->RightChild())); } } } template void BinaryTree::MapPostOrder(const typename MappableContainer::MapFunctor function, void* par, Node* node){ if(node != nullptr){ if(node->HasLeftChild()){ MapPostOrder(function, par, &(node->LeftChild())); } if(node->HasRightChild()){ MapPostOrder(function, par, &(node->RightChild())); } function(node->Element(), par); } } template void BinaryTree::MapInOrder(const typename MappableContainer::MapFunctor function, void* par, Node* node){ if(node != nullptr){ if(node->HasLeftChild()){ MapInOrder(function, par, &(node->LeftChild())); } function(node->Element(), par); if(node->HasRightChild()){ MapInOrder(function, par, &(node->RightChild())); } } } template void BinaryTree::MapBreadth(const typename MappableContainer::MapFunctor function, void* par, Node* node){ QueueLst toVisit; if(node != nullptr){ toVisit.Enqueue(node); while(!toVisit.Empty()){ function(toVisit.Head()->Element(), par); if(toVisit.Head()->HasLeftChild()){ toVisit.Enqueue(&(toVisit.Head()->LeftChild())); } if(toVisit.Head()->HasRightChild()){ toVisit.Enqueue(&(toVisit.Head()->RightChild())); } toVisit.Dequeue(); } } } template void BinaryTree::FoldPreOrder(const typename FoldableContainer::FoldFunctor function, const void* par, void* acc, const Node* node) const{ if(node != nullptr){ function(node->Element(), par, acc); if(node->HasLeftChild()){ FoldPreOrder(function, par, acc, &(node->LeftChild())); } if(node->HasRightChild()){ FoldPreOrder(function, par, acc, &(node->RightChild())); } } } template void BinaryTree::FoldPostOrder(const typename FoldableContainer::FoldFunctor function, const void* par, void* acc, const Node* node) const{ if(node != nullptr){ if(node->HasLeftChild()){ FoldPostOrder(function, par, acc, &(node->LeftChild())); } if(node->HasRightChild()){ FoldPostOrder(function, par, acc, &(node->RightChild())); } function(node->Element(), par, acc); } } template void BinaryTree::FoldInOrder(const typename FoldableContainer::FoldFunctor function, const void* par, void* acc, const Node* node) const{ if(node != nullptr){ if(node->HasLeftChild()){ FoldInOrder(function, par, acc, &(node->LeftChild())); } function(node->Element(), par, acc); if(node->HasRightChild()){ FoldInOrder(function, par, acc, &(node->RightChild())); } } } template void BinaryTree::FoldBreadth(const typename FoldableContainer::FoldFunctor function, const void* par, void* acc, Node* node) const{ QueueLst::Node*> toVisit; if(node != nullptr){ toVisit.Enqueue(node); while(!toVisit.Empty()){ function(toVisit.Head()->Element(), par, acc); if(toVisit.Head()->HasLeftChild()){ toVisit.Enqueue(&(toVisit.Head()->LeftChild())); } if(toVisit.Head()->HasRightChild()){ toVisit.Enqueue(&(toVisit.Head()->RightChild())); } toVisit.Dequeue(); } } } /* ----- end of class BinaryTree ----- */ /* ----- begin of class BTPreOrderIterator ----- */ template BTPreOrderIterator::BTPreOrderIterator(const BinaryTree& tree){ if(tree.Size() > 0) curr = &tree.Root(); else curr = nullptr; } template BTPreOrderIterator::BTPreOrderIterator(const BTPreOrderIterator& itr){ curr = itr.curr; stack = itr.stack; } template BTPreOrderIterator::BTPreOrderIterator(BTPreOrderIterator&& itr) noexcept{ std::swap(curr, itr.curr); std::swap(stack, itr.stack); } template BTPreOrderIterator::~BTPreOrderIterator(){ stack.Clear(); curr = nullptr; } template BTPreOrderIterator& BTPreOrderIterator::operator=(const BTPreOrderIterator& itr){ curr = itr.curr; stack = itr.stack; return *this; } template BTPreOrderIterator& BTPreOrderIterator::operator=(BTPreOrderIterator&& itr) noexcept{ std::swap(curr, itr.curr); std::swap(stack, itr.stack); return *this; } template bool BTPreOrderIterator::operator==(const BTPreOrderIterator& itr) const noexcept{ return ( curr==itr.curr && stack==itr.stack ); } template bool BTPreOrderIterator::operator!=(const BTPreOrderIterator& itr) const noexcept{ return !(*this == itr); } template Data& BTPreOrderIterator::operator*() const{ if(Terminated()) throw std::out_of_range("Iterator is terminated!"); return curr->Element(); } template bool BTPreOrderIterator::Terminated() const noexcept{ return (curr==nullptr); } template void BTPreOrderIterator::operator++(){ if(Terminated()) throw std::out_of_range("Iterator is terminated!"); if(curr->HasLeftChild()){ if( curr->HasRightChild() ){ stack.Push(&(curr->RightChild())); } curr = &(curr->LeftChild()); }else if(curr->HasRightChild()){ curr = &curr->RightChild(); } else{ // is leaf if(stack.Empty()){ curr = nullptr; }else{ curr = stack.TopNPop(); } } } /* ----- end of class BTPreOrderIterator ----- */ /* ----- begin of class BTPostOrderIterator ----- */ template struct BinaryTree::Node* BTPostOrderIterator::DeepestLeftLeaf(struct BinaryTree::Node* node){ if(node->HasLeftChild()){ stack.Push(node); return DeepestLeftLeaf(&(node->LeftChild())); } else if(node->HasRightChild()){ stack.Push(node); return DeepestLeftLeaf(&(node->RightChild())); } else return node; } template BTPostOrderIterator::BTPostOrderIterator(const BinaryTree& tree){ if(tree.Size() > 0) curr = DeepestLeftLeaf(&tree.Root()); else curr = nullptr; } template BTPostOrderIterator::BTPostOrderIterator(const BTPostOrderIterator& itr){ curr = itr.curr; stack = itr.stack; } template BTPostOrderIterator::BTPostOrderIterator(BTPostOrderIterator&& itr) noexcept{ std::swap(curr, itr.curr); std::swap(stack, itr.stack); } template BTPostOrderIterator::~BTPostOrderIterator(){ curr = nullptr; stack.Clear(); } template BTPostOrderIterator& BTPostOrderIterator::operator=(const BTPostOrderIterator& itr){ curr = itr.curr; stack = itr.stack; return *this; } template BTPostOrderIterator& BTPostOrderIterator::operator=(BTPostOrderIterator&& itr) noexcept{ std::swap(curr, itr.curr); std::swap(stack, itr.stack); return *this; } template bool BTPostOrderIterator::operator==(const BTPostOrderIterator& itr) const noexcept{ return (curr == itr.curr && stack == itr.stack ); } template bool BTPostOrderIterator::operator!=(const BTPostOrderIterator& itr) const noexcept{ return !(*this == itr); } template Data& BTPostOrderIterator::operator*() const{ if(Terminated()) throw std::out_of_range("Iterator is terminated!"); return curr->Element(); } template bool BTPostOrderIterator::Terminated() const noexcept{ return (curr == nullptr); } template void BTPostOrderIterator::operator++(){ /* * If we're coming from the left then we have to analyze the tree on the right * (if existent). Otherwise we just top 'n' pop. */ if(Terminated()) throw std::out_of_range("Iterator is terminated!"); if(stack.Empty()){ curr = nullptr; }else{ if((stack.Top())->HasLeftChild() && curr == &((stack.Top())->LeftChild()) ){ if( (stack.Top())->HasRightChild() ){ curr = DeepestLeftLeaf(&((stack.Top())->RightChild())); }else{ curr = stack.TopNPop(); } }else{ curr = stack.TopNPop(); } } } /* ----- end of class BTPostOrderIterator ----- */ /* ----- begin of class BTInOrderIterator ----- */ template struct BinaryTree::Node* BTInOrderIterator::MostLeftNode(struct BinaryTree::Node& root){ if(root.HasLeftChild()){ stack.Push(&root); return MostLeftNode(root.LeftChild()); }else{ return &root; } } template BTInOrderIterator::BTInOrderIterator(const BinaryTree& tree){ if(tree.Size() > 0) curr = MostLeftNode(tree.Root()); else curr = nullptr; } template BTInOrderIterator::BTInOrderIterator(const BTInOrderIterator& itr){ curr = itr.curr; stack = itr.stack; } template BTInOrderIterator::BTInOrderIterator(BTInOrderIterator&& toMove) noexcept{ std::move(curr, toMove.curr); std::move(stack, toMove.stack); } template BTInOrderIterator::~BTInOrderIterator(){ stack.Clear(); curr = nullptr; } template BTInOrderIterator& BTInOrderIterator::operator=(const BTInOrderIterator& itr){ curr = itr.curr; stack = itr.stack; return *this; } template BTInOrderIterator& BTInOrderIterator::operator=(BTInOrderIterator&& toMove) noexcept{ std::move(curr, toMove.curr); std::move(stack, toMove.stack); return *this; } template bool BTInOrderIterator::operator==(const BTInOrderIterator& itr) const noexcept{ return (curr == itr.curr && stack == itr.stack ); } template bool BTInOrderIterator::operator!=(const BTInOrderIterator& itr) const noexcept{ return !(*this == itr); } template Data& BTInOrderIterator::operator*() const{ if(Terminated()) throw std::out_of_range("Iterator is terminated!"); return curr->Element(); } template bool BTInOrderIterator::Terminated() const noexcept{ return (curr == nullptr); } template void BTInOrderIterator::operator++(){ if(Terminated()) throw std::out_of_range("Iterator is terminated!"); if(curr->HasRightChild()){ curr = MostLeftNode(curr->RightChild()); }else{ if(stack.Empty()){ curr = nullptr; }else{ curr = stack.TopNPop(); } } } /* ----- end of class BTInOrderIterator ----- */ /* ----- begin of class BTBreadthIteratorOrderIterator ----- */ template BTBreadthIterator::BTBreadthIterator(const BinaryTree& tree){ if(tree.Size() > 0) curr = &(tree.Root()); else curr = nullptr; } template BTBreadthIterator::BTBreadthIterator(const BTBreadthIterator& itr){ curr = itr.curr; queue = itr.queue; } template BTBreadthIterator::BTBreadthIterator(BTBreadthIterator&& itr) noexcept{ std::swap(curr, itr.curr); std::swap(queue, itr.queue); } template BTBreadthIterator::~BTBreadthIterator(){ curr = nullptr; queue.Clear(); } template BTBreadthIterator& BTBreadthIterator::operator=(const BTBreadthIterator& itr){ curr = itr.curr; queue = itr.queue; return *this; } template BTBreadthIterator& BTBreadthIterator::operator=(BTBreadthIterator&& itr) noexcept{ std::swap(curr, itr.curr); std::swap(queue, itr.queue); return *this; } template bool BTBreadthIterator::operator==(const BTBreadthIterator& itr) const noexcept{ return ( curr==itr.curr && queue==itr.queue ); } template bool BTBreadthIterator::operator!=(const BTBreadthIterator& itr) const noexcept{ return !(*this == itr); } template Data& BTBreadthIterator::operator*() const{ if(Terminated()) throw std::out_of_range("Iterator is terminated!"); return curr->Element(); } template bool BTBreadthIterator::Terminated() const noexcept{ return curr == nullptr; } template void BTBreadthIterator::operator++(){ if(Terminated()) throw std::out_of_range("Iterator is terminated!"); if(curr->HasLeftChild()){ queue.Enqueue(&(curr->LeftChild())); } if(curr->HasRightChild()){ queue.Enqueue(&(curr->RightChild())); } if(!queue.Empty()){ curr = queue.HeadNDequeue(); }else{ curr = nullptr; } } /* ************************************************************************** */ }