From 65996765d11cbcae23d23f3dabe2a3957bb3603a Mon Sep 17 00:00:00 2001 From: Jesse Millwood Date: Wed, 30 Oct 2024 14:27:57 -0400 Subject: [PATCH] Add iterative version of binary tree traversal and enum to switch algo --- Readme.org | 8 +-- libs/dope/bintree.hpp | 154 ++++++++++++++++++++++++++++++++++++++---- tests/test.cpp | 39 ++++++++++- 3 files changed, 181 insertions(+), 20 deletions(-) diff --git a/Readme.org b/Readme.org index ecae0ed..ce7a0c4 100644 --- a/Readme.org +++ b/Readme.org @@ -60,15 +60,15 @@ To run the tests: ** Stacks and Queues [0/2] - [ ] Stack Min (CTCI: 3.1) - [ ] Sort Stack (CTCI: 3.5) -** Trees and Graphs [4/9] +** Trees and Graphs [7/9] - [X] Implement binary tree object - Insert breadth first - [X] Recursive Pre-order traversal - [X] Recursive In-order traversal - [X] Recursive Post-order traversal -- [ ] Non-Recursive Pre-order traversal -- [ ] Non-Recursive In-order traversal -- [ ] Non-Recursive Post-order traversal +- [X] Non-Recursive Pre-order traversal +- [X] Non-Recursive In-order traversal +- [X] Non-Recursive Post-order traversal - [ ] Min Heap - [ ] Binary Search ** C/C++ [2/5] diff --git a/libs/dope/bintree.hpp b/libs/dope/bintree.hpp index b521e41..aae3006 100644 --- a/libs/dope/bintree.hpp +++ b/libs/dope/bintree.hpp @@ -1,6 +1,12 @@ #pragma once #include +#include + +typedef enum AlgoVariant_E{ + Recursive, + Iter, +}AlgoVariant; template class DopeBinTreeNode{ @@ -23,6 +29,9 @@ class DopeBinTree{ 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(); @@ -30,9 +39,9 @@ public: void insert(T data); bool isEmpty(); DopeBinTreeNode* 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::RecPostOrderTraversal(DopeBinTreeNode* node, T* out){ } template -void DopeBinTree::RecPreOrderTraversalArray(T* array){ - int index = 0; - DopeBinTreeNode* node = root; +void DopeBinTree::IterPreOrderTraversal(DopeBinTreeNode* node, T* out){ + std::stack*> s = {}; + s.push(node); - RecPreOrderTraversal(node, &array[index]); + 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::RecInOrderTraversalArray(T* array){ - int index = 0; - DopeBinTreeNode* node = root; +void DopeBinTree::IterPostOrderTraversal(DopeBinTreeNode* node, T* out){ + std::stack*> s_tmp = {}; + std::stack*> s_fin = {}; - RecInOrderTraversal(node, &array[index]); + 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::RecPostOrderTraversalArray(T* array){ +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; - RecPostOrderTraversal(node, &array[index]); + switch(variant){ + case AlgoVariant::Recursive: + RecPostOrderTraversal(node, &array[index]); + return; + case AlgoVariant::Iter: + IterPostOrderTraversal(node, &array[index]); + return; + default: + return; + } } diff --git a/tests/test.cpp b/tests/test.cpp index 93882b9..1e47da6 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -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]);