#pragma once #include #include typedef enum AlgoVariant_E{ Recursive, Iter, }AlgoVariant; template class DopeBinTreeNode{ DopeBinTreeNode* left; DopeBinTreeNode* right; T data; public: DopeBinTreeNode(T data); ~DopeBinTreeNode(); void SetLeft(DopeBinTreeNode* newleft){left = newleft;} void SetRight(DopeBinTreeNode* newright){right = newright;} DopeBinTreeNode* GetLeft(){return left;} DopeBinTreeNode* GetRight(){return right;} T GetData(){return data;} }; template class DopeBinTree{ DopeBinTreeNode* root; T* RecPreOrderTraversal(DopeBinTreeNode* node, T* out); T* RecInOrderTraversal(DopeBinTreeNode* node, T* out); T* RecPostOrderTraversal(DopeBinTreeNode* node, T* out); void IterPreOrderTraversal(DopeBinTreeNode* node, T* out); void IterInOrderTraversal(DopeBinTreeNode* node, T* out); void IterPostOrderTraversal(DopeBinTreeNode* node, T* out); public: DopeBinTree(T data); DopeBinTree(); ~DopeBinTree(); void insert(T data); bool isEmpty(); DopeBinTreeNode* getRoot(){return root;} void PreOrderTraversal2Array(T* array, AlgoVariant variant); void InOrderTraversal2Array(T* array, AlgoVariant variant); void PostOrderTraversal2Array(T* array, AlgoVariant variant); }; // Implementations ___________________________________________________ template DopeBinTreeNode::DopeBinTreeNode(T node_data): left(nullptr), right(nullptr), data(node_data) { } template DopeBinTreeNode::~DopeBinTreeNode(){ delete left; delete right; } template DopeBinTree::DopeBinTree(T data){ root = new DopeBinTreeNode(data); } template DopeBinTree::DopeBinTree(): root(nullptr) { } template DopeBinTree::~DopeBinTree(){ if (root != nullptr){ delete root; } } template // Insert Breadth first void DopeBinTree::insert(T data){ DopeBinTreeNode* current_node = root; if (root == nullptr){ root = new DopeBinTreeNode(data); } else { auto new_node = new DopeBinTreeNode(data); // Breadth first traversal std::queue*> q; q.push(root); while(!q.empty()){ current_node = q.front(); q.pop(); if(current_node->GetLeft()){ q.push(current_node->GetLeft()); } else { current_node->SetLeft(new_node); break; } if(current_node->GetRight()){ q.push(current_node->GetRight()); } else { current_node->SetRight(new_node); break; } } } } template bool DopeBinTree::isEmpty(){ if(root == nullptr){ return true; } else { return false; } } template T* DopeBinTree::RecPreOrderTraversal(DopeBinTreeNode* node, T* out){ if (node == nullptr){ return out--; } *out = node->GetData(); out++; out = RecPreOrderTraversal(node->GetLeft(), out); out = RecPreOrderTraversal(node->GetRight(), out); return out; } template T* DopeBinTree::RecInOrderTraversal(DopeBinTreeNode* node, T* out){ if (node == nullptr){ return out--; } out = RecInOrderTraversal(node->GetLeft(), out); *out = node->GetData(); out++; out = RecInOrderTraversal(node->GetRight(), out); return out; } template T* DopeBinTree::RecPostOrderTraversal(DopeBinTreeNode* node, T* out){ if (node == nullptr){ return out--; } out = RecPostOrderTraversal(node->GetLeft(), out); out = RecPostOrderTraversal(node->GetRight(), out); *out = node->GetData(); out++; return out; } template void DopeBinTree::IterPreOrderTraversal(DopeBinTreeNode* node, T* out){ std::stack*> s = {}; s.push(node); while(s.empty() == false){ node = s.top(); s.pop(); *out = node->GetData(); out++; if(node->GetRight()){ s.push(node->GetRight()); } if(node->GetLeft()){ s.push(node->GetLeft()); } } } template void DopeBinTree::IterInOrderTraversal(DopeBinTreeNode* node, T* out){ std::stack*> s = {}; while (!s.empty() || node){ while(node != nullptr){ s.push(node); node = node->GetLeft(); } node = s.top(); s.pop(); *out = node->GetData(); out++; node = node->GetRight(); } } template void DopeBinTree::IterPostOrderTraversal(DopeBinTreeNode* node, T* out){ std::stack*> s_tmp = {}; std::stack*> s_fin = {}; s_tmp.push(node); while(!s_tmp.empty()){ node = s_tmp.top(); s_tmp.pop(); s_fin.push(node); if(node->GetLeft()){ s_tmp.push(node->GetLeft()); } if(node->GetRight()){ s_tmp.push(node->GetRight()); } } while(!s_fin.empty()){ node = s_fin.top(); s_fin.pop(); *out = node->GetData(); out++; } } /** * \brief PreOrderTraversal2Array * * Binary tree traversal that visits the root node, then the left * sub-tree, and then the right-subtree. * * \param The output array * \param The algorithm variant * \return return type */ template void DopeBinTree::PreOrderTraversal2Array(T* array, AlgoVariant variant){ int index = 0; DopeBinTreeNode* node = root; switch(variant){ case AlgoVariant::Recursive: RecPreOrderTraversal(node, &array[index]); return; case AlgoVariant::Iter: IterPreOrderTraversal(node, &array[index]); return; default: return; } } /** * \brief InOrderTraversal2Array * * Binary tree traversal that traverses the left sub-tree, then * visits the root node, then the right-subtree. * * \param The output array * \param The algorithm variant * \return return type */ template void DopeBinTree::InOrderTraversal2Array(T* array, AlgoVariant variant){ int index = 0; DopeBinTreeNode* node = root; switch(variant){ case AlgoVariant::Recursive: RecInOrderTraversal(node, &array[index]); return; case AlgoVariant::Iter: IterInOrderTraversal(node, &array[index]); return; default: return; } } /** * \brief PostOrderTraversal2Array * * Binary tree traversal that visits left-subtree, right subtree, and * then the root node. * * \param The output array * \param The algorithm variant * \return return type */ template void DopeBinTree::PostOrderTraversal2Array(T* array, AlgoVariant variant){ int index = 0; DopeBinTreeNode* node = root; switch(variant){ case AlgoVariant::Recursive: RecPostOrderTraversal(node, &array[index]); return; case AlgoVariant::Iter: IterPostOrderTraversal(node, &array[index]); return; default: return; } }