301 lines
6.6 KiB
C++
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;
|
|
}
|
|
}
|