Add iterative version of binary tree traversal and enum to switch algo

This commit is contained in:
Jesse Millwood 2024-10-30 14:27:57 -04:00
parent 011236f238
commit 54c2054bf2
2 changed files with 177 additions and 16 deletions

View File

@ -1,6 +1,12 @@
#pragma once
#include <queue>
#include <stack>
typedef enum AlgoVariant_E{
Recursive,
Iter,
}AlgoVariant;
template <class T>
class DopeBinTreeNode{
@ -23,6 +29,9 @@ class DopeBinTree{
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();
@ -30,9 +39,9 @@ public:
void insert(T data);
bool isEmpty();
DopeBinTreeNode<T>* getRoot(){return root;}
void RecPreOrderTraversalArray(T* array);
void RecInOrderTraversalArray(T* array);
void RecPostOrderTraversalArray(T* array);
void PreOrderTraversal2Array(T* array, AlgoVariant variant);
void InOrderTraversal2Array(T* array, AlgoVariant variant);
void PostOrderTraversal2Array(T* array, AlgoVariant variant);
};
// Implementations ___________________________________________________
@ -147,26 +156,145 @@ T* DopeBinTree<T>::RecPostOrderTraversal(DopeBinTreeNode<T>* node, T* out){
}
template <class T>
void DopeBinTree<T>::RecPreOrderTraversalArray(T* array){
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>::RecInOrderTraversalArray(T* array){
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>::RecPostOrderTraversalArray(T* array){
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;
}
}

View File

@ -136,7 +136,7 @@ TEST(ChapterFour, TreeTraversal){
int array[10] = {};
btree.RecPreOrderTraversalArray(array);
btree.PreOrderTraversal2Array(array, AlgoVariant::Recursive);
CHECK_EQUAL(1, array[0]);
CHECK_EQUAL(2, array[1]);
CHECK_EQUAL(4, array[2]);
@ -147,7 +147,7 @@ TEST(ChapterFour, TreeTraversal){
std::fill(array, array+10, 0);
btree.RecInOrderTraversalArray(array);
btree.InOrderTraversal2Array(array, AlgoVariant::Recursive);
CHECK_EQUAL(4, array[0]);
CHECK_EQUAL(2, array[1]);
CHECK_EQUAL(5, array[2]);
@ -158,7 +158,40 @@ TEST(ChapterFour, TreeTraversal){
std::fill(array, array+10, 0);
btree.RecPostOrderTraversalArray(array);
btree.PostOrderTraversal2Array(array, AlgoVariant::Recursive);
CHECK_EQUAL(4, array[0]);
CHECK_EQUAL(5, array[1]);
CHECK_EQUAL(2, array[2]);
CHECK_EQUAL(6, array[3]);
CHECK_EQUAL(7, array[4]);
CHECK_EQUAL(3, array[5]);
CHECK_EQUAL(1, array[6]);
std::fill(array, array+10, 0);
btree.PreOrderTraversal2Array(array, AlgoVariant::Iter);
CHECK_EQUAL(1, array[0]);
CHECK_EQUAL(2, array[1]);
CHECK_EQUAL(4, array[2]);
CHECK_EQUAL(5, array[3]);
CHECK_EQUAL(3, array[4]);
CHECK_EQUAL(6, array[5]);
CHECK_EQUAL(7, array[6]);
std::fill(array, array+10, 0);
btree.InOrderTraversal2Array(array, AlgoVariant::Iter);
CHECK_EQUAL(4, array[0]);
CHECK_EQUAL(2, array[1]);
CHECK_EQUAL(5, array[2]);
CHECK_EQUAL(1, array[3]);
CHECK_EQUAL(6, array[4]);
CHECK_EQUAL(3, array[5]);
CHECK_EQUAL(7, array[6]);
std::fill(array, array+10, 0);
btree.PostOrderTraversal2Array(array, AlgoVariant::Iter);
CHECK_EQUAL(4, array[0]);
CHECK_EQUAL(5, array[1]);
CHECK_EQUAL(2, array[2]);