dsa-practice/libs/dope/bintree.hpp

301 lines
6.6 KiB
C++

#pragma once
#include <queue>
#include <stack>
typedef enum AlgoVariant_E{
Recursive,
Iter,
}AlgoVariant;
template <class T>
class DopeBinTreeNode{
DopeBinTreeNode<T>* left;
DopeBinTreeNode<T>* right;
T data;
public:
DopeBinTreeNode(T data);
~DopeBinTreeNode();
void SetLeft(DopeBinTreeNode<T>* newleft){left = newleft;}
void SetRight(DopeBinTreeNode<T>* newright){right = newright;}
DopeBinTreeNode<T>* GetLeft(){return left;}
DopeBinTreeNode<T>* GetRight(){return right;}
T GetData(){return data;}
};
template <class T>
class DopeBinTree{
DopeBinTreeNode<T>* root;
T* RecPreOrderTraversal(DopeBinTreeNode<T>* node, T* out);
T* RecInOrderTraversal(DopeBinTreeNode<T>* node, T* out);
T* RecPostOrderTraversal(DopeBinTreeNode<T>* node, T* out);
void IterPreOrderTraversal(DopeBinTreeNode<T>* node, T* out);
void IterInOrderTraversal(DopeBinTreeNode<T>* node, T* out);
void IterPostOrderTraversal(DopeBinTreeNode<T>* node, T* out);
public:
DopeBinTree(T data);
DopeBinTree();
~DopeBinTree();
void insert(T data);
bool isEmpty();
DopeBinTreeNode<T>* getRoot(){return root;}
void PreOrderTraversal2Array(T* array, AlgoVariant variant);
void InOrderTraversal2Array(T* array, AlgoVariant variant);
void PostOrderTraversal2Array(T* array, AlgoVariant variant);
};
// Implementations ___________________________________________________
template <class T>
DopeBinTreeNode<T>::DopeBinTreeNode(T node_data):
left(nullptr),
right(nullptr),
data(node_data)
{
}
template <class T>
DopeBinTreeNode<T>::~DopeBinTreeNode(){
delete left;
delete right;
}
template <class T>
DopeBinTree<T>::DopeBinTree(T data){
root = new DopeBinTreeNode<T>(data);
}
template <class T>
DopeBinTree<T>::DopeBinTree():
root(nullptr)
{
}
template <class T>
DopeBinTree<T>::~DopeBinTree(){
if (root != nullptr){
delete root;
}
}
template <class T>
// Insert Breadth first
void DopeBinTree<T>::insert(T data){
DopeBinTreeNode<T>* current_node = root;
if (root == nullptr){
root = new DopeBinTreeNode<T>(data);
} else {
auto new_node = new DopeBinTreeNode<T>(data);
// Breadth first traversal
std::queue<DopeBinTreeNode<T>*> 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 <class T>
bool DopeBinTree<T>::isEmpty(){
if(root == nullptr){
return true;
} else {
return false;
}
}
template <class T>
T* DopeBinTree<T>::RecPreOrderTraversal(DopeBinTreeNode<T>* 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 <class T>
T* DopeBinTree<T>::RecInOrderTraversal(DopeBinTreeNode<T>* 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 <class T>
T* DopeBinTree<T>::RecPostOrderTraversal(DopeBinTreeNode<T>* 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 <class T>
void DopeBinTree<T>::IterPreOrderTraversal(DopeBinTreeNode<T>* node, T* out){
std::stack<DopeBinTreeNode<T>*> 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 <class T>
void DopeBinTree<T>::IterInOrderTraversal(DopeBinTreeNode<T>* node, T* out){
std::stack<DopeBinTreeNode<T>*> 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 <class T>
void DopeBinTree<T>::IterPostOrderTraversal(DopeBinTreeNode<T>* node, T* out){
std::stack<DopeBinTreeNode<T>*> s_tmp = {};
std::stack<DopeBinTreeNode<T>*> 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 <class T>
void DopeBinTree<T>::PreOrderTraversal2Array(T* array, AlgoVariant variant){
int index = 0;
DopeBinTreeNode<T>* 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 <class T>
void DopeBinTree<T>::InOrderTraversal2Array(T* array, AlgoVariant variant){
int index = 0;
DopeBinTreeNode<T>* 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 <class T>
void DopeBinTree<T>::PostOrderTraversal2Array(T* array, AlgoVariant variant){
int index = 0;
DopeBinTreeNode<T>* node = root;
switch(variant){
case AlgoVariant::Recursive:
RecPostOrderTraversal(node, &array[index]);
return;
case AlgoVariant::Iter:
IterPostOrderTraversal(node, &array[index]);
return;
default:
return;
}
}