Skip to content

Commit 47c8413

Browse files
motasimmakkigithub-actionsPanquesito7manncodes
authored
feat: Added implementation of iterative version of tree traversals. (TheAlgorithms#1506)
* feat: Added iterative version of tree traversals. Here is the implementation of the iterative version of the Preorder, Postorder, and the Inorder traversal of given tree. . Time Complexity: O(n), where 'n' is the total number of nodes in a tree. * updating DIRECTORY.md * fixed: function descriptions, namespace declaration, and included separate libraries. * fixed: added range bases for loops. * style: proper indentation Co-authored-by: David Leal <halfpacho@gmail.com> * style: proper indentation Co-authored-by: David Leal <halfpacho@gmail.com> * style: proper indentation Co-authored-by: David Leal <halfpacho@gmail.com> * fix: C style NULL to nullptr Co-authored-by: David Leal <halfpacho@gmail.com> * docs: spell correction Co-authored-by: David Leal <halfpacho@gmail.com> * style: formatted comments. * fixes: static_cast, if and for statement braces * style: modified pointer declaration. * fixes: removed use of typedef, renamed BT to Node * Fix `clang-tidy` warnings * fix: Try to fix `clang-tidy` warnings this time * docs: Proper function description Co-authored-by: Mann Patel <46739555+manncodes@users.noreply.github.com> * fix: Class based approach * docs: Proper formatted comment Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper indentation Co-authored-by: David Leal <halfpacho@gmail.com> * fix: Initialized data variable Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper formatted comment Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper indentation Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper formatted comment Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper function description Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Removed unnecessary comment Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper formatted comment Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper function description * docs: Proper variables description Co-authored-by: Mann Patel <46739555+manncodes@users.noreply.github.com> * docs: Included variables description Co-authored-by: Mann Patel <46739555+manncodes@users.noreply.github.com> * docs: Included variables description Co-authored-by: Mann Patel <46739555+manncodes@users.noreply.github.com> * docs: Proper variables description Co-authored-by: Mann Patel <46739555+manncodes@users.noreply.github.com> * fixes: Self-test implementation and namespace * docs: Documentation improvements * docs: Proper formatted description Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper formatted description Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper formatted description Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper formatted description Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper indentation Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper formatted description Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Improved function description * docs: Proper formatted description Co-authored-by: David Leal <halfpacho@gmail.com> * test: Added test cases for negative values * docs: Proper description Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper formatted comment Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper formatted comment Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper function description Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper formatted description Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper description Co-authored-by: David Leal <halfpacho@gmail.com> * docs: Proper description Co-authored-by: David Leal <halfpacho@gmail.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal <halfpacho@gmail.com> Co-authored-by: Mann Patel <46739555+manncodes@users.noreply.github.com>
1 parent d54afc5 commit 47c8413

File tree

2 files changed

+363
-0
lines changed

2 files changed

+363
-0
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@
229229
* [Decimal To Roman Numeral](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/decimal_to_roman_numeral.cpp)
230230
* [Fast Integer Input](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/fast_integer_input.cpp)
231231
* [Happy Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/happy_number.cpp)
232+
* [Iterative Tree Traversals](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/iterative_tree_traversals.cpp)
232233
* [Matrix Exponentiation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/matrix_exponentiation.cpp)
233234
* [Palindrome Of Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/palindrome_of_number.cpp)
234235
* [Paranthesis Matching](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/paranthesis_matching.cpp)

others/iterative_tree_traversals.cpp

Lines changed: 362 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,362 @@
1+
/**
2+
* @file
3+
* @brief Iterative version of Preorder, Postorder, and preorder [Traversal of the Tree]
4+
* (https://en.wikipedia.org/wiki/Tree_traversal)
5+
* @author [Motasim](https://github.com/motasimmakki)
6+
* @details
7+
*
8+
* ### Iterative Preorder Traversal of a tree
9+
* Create a Stack that will store the Node of Tree.
10+
* Push the root node into the stack.
11+
* Save the root into the variabe named as current, and pop and elemnt from the stack.
12+
* Store the data of current into the result array, and start traversing from it.
13+
* Push both the child node of the current node into the stack, first right child then left child.
14+
* Repeat the same set of steps untill the Stack becomes empty.
15+
* And return the result array as the preorder traversal of a tree.
16+
*
17+
* ### Iterative Postorder Traversal of a tree
18+
* Create a Stack that will store the Node of Tree.
19+
* Push the root node into the stack.
20+
* Save the root into the variabe named as current, and pop and elemnt from the stack.
21+
* Store the data of current into the result array, and start traversing from it.
22+
* Push both the child node of the current node into the stack, first left child then right child.
23+
* Repeat the same set of steps untill the Stack becomes empty.
24+
* Now reverse the result array and then return it to the calling function as a postorder traversal of a tree.
25+
*
26+
* ### Iterative Inorder Traversal of a tree
27+
* Create a Stack that will store the Node of Tree.
28+
* Push the root node into the stack.
29+
* Save the root into the variabe named as current.
30+
* Now iterate and take the current to the extreme left of the tree by traversing only to its left.
31+
* Pop the elemnt from the stack and assign it to the current.
32+
* Store the data of current into the result array.
33+
* Repeat the same set of steps until the Stack becomes empty or the current becomes NULL.
34+
* And return the result array as the inorder traversal of a tree.
35+
*/
36+
#include <iostream> /// for I/O operations
37+
#include <stack> /// for `stack`
38+
#include <vector> /// for `vector`
39+
#include <algorithm> /// for `reverse`
40+
#include <cassert> /// for `assert`
41+
42+
/**
43+
* @namespace others
44+
* @brief Other algorithms
45+
*/
46+
namespace others {
47+
/**
48+
* @namespace iterative_tree_traversals
49+
* @brief Functions for the [Traversal of the Tree](https://en.wikipedia.org/wiki/Tree_traversal) algorithm
50+
*/
51+
namespace iterative_tree_traversals {
52+
/**
53+
* @brief defines the structure of a node of the tree
54+
*/
55+
struct Node {
56+
int64_t data = 0; ///< The value/key of the node.
57+
struct Node *left; ///< struct pointer to left subtree.
58+
struct Node *right; ///< struct pointer to right subtree.
59+
};
60+
61+
/**
62+
* @brief defines the functions associated with the binary tree
63+
*/
64+
class BinaryTree {
65+
public:
66+
Node *createNewNode(int64_t); ///< function that will create new node for insertion.
67+
std::vector<int64_t> preOrderIterative(Node *); ///< function that takes root of the tree as an argument, and returns its preorder traversal.
68+
std::vector<int64_t> postOrderIterative(Node *); ///< function that takes root of the tree as an argument, and returns its postorder traversal.
69+
std::vector<int64_t> inOrderIterative(Node *); ///< function that takes root of the tree as an argument, and returns its inorder traversal.
70+
};
71+
72+
/**
73+
* @brief will allocate the memory for a node and, along the data and return the node.
74+
* @param data value that a particular node will contain.
75+
* @return pointer to the newly created node with assigned data.
76+
*/
77+
Node * BinaryTree::createNewNode(int64_t data) {
78+
Node *node = new Node();
79+
node->data = data;
80+
node->left = node->right = nullptr;
81+
return node;
82+
}
83+
84+
/**
85+
* @brief preOrderIterative() function that will perform the preorder traversal iteratively,
86+
* and return the result array that contain the preorder traversal of a tree.
87+
* @param root head/root node of a tree
88+
* @return result that is containing the preorder traversal of a tree
89+
*/
90+
std::vector<int64_t> BinaryTree::preOrderIterative(Node *root) {
91+
std::stack<Node *> stack; ///< is used to find and traverse the child nodes.
92+
std::vector<int64_t> result; ///< list of values, sorted in pre-order.
93+
94+
stack.push(root);
95+
96+
while(!stack.empty()) {
97+
result.push_back(stack.top()->data);
98+
Node *current = stack.top();
99+
stack.pop();
100+
101+
if(current->right) {
102+
stack.push(current->right);
103+
}
104+
if(current->left) {
105+
stack.push(current->left);
106+
}
107+
}
108+
109+
return result;
110+
}
111+
112+
/**
113+
* @brief postOrderIterative() function that will perform the postorder traversal iteratively,
114+
* and return the result array that contain the postorder traversal of a tree.
115+
* @param root head/root node of a tree
116+
* @return result that is containing the postorder traversal of a tree
117+
*/
118+
std::vector<int64_t> BinaryTree::postOrderIterative(Node *root) {
119+
std::stack<Node *> stack; ///< is used to find and traverse the child nodes.
120+
std::vector<int64_t> result; ///< List of values, sorted in post-order.
121+
122+
stack.push(root);
123+
124+
while(!stack.empty()) {
125+
result.push_back(stack.top()->data);
126+
Node *current = stack.top();
127+
stack.pop();
128+
129+
if(current->left) {
130+
stack.push(current->left);
131+
}
132+
if(current->right) {
133+
stack.push(current->right);
134+
}
135+
}
136+
137+
reverse(result.begin(), result.end());
138+
139+
return result;
140+
}
141+
142+
/**
143+
* @brief inOrderIterative() function that will perform the inorder traversal iteratively,
144+
* and return the result array that contain the inorder traversal of a tree.
145+
* @param root head/root node of a tree
146+
* @return result that is containing the inorder traversal of a tree
147+
*/
148+
std::vector<int64_t> BinaryTree::inOrderIterative(Node *root) {
149+
std::stack<Node *> stack; ///< is used to find and traverse the child nodes.
150+
std::vector<int64_t> result; ///< List of values, sorted in in-order.
151+
152+
Node *current = root;
153+
154+
while(!stack.empty() || current) {
155+
while(current) {
156+
stack.push(current);
157+
current = current->left;
158+
}
159+
current = stack.top();
160+
stack.pop();
161+
result.push_back(current->data);
162+
current = current->right;
163+
}
164+
return result;
165+
}
166+
} // namespace iterative_tree_traversals
167+
} // namespace others
168+
169+
/**
170+
* @brief Test the computed preorder with the actual preorder.
171+
* @param binaryTree instance of the BinaryTree class
172+
* @param root head/root node of a tree
173+
*/
174+
static void test1(others::iterative_tree_traversals::BinaryTree binaryTree, others::iterative_tree_traversals::Node *root){
175+
std::vector<int64_t> actual_result{1, 2, 4, 5, 3};
176+
std::vector<int64_t> result; ///< result stores the preorder traversal of the binary tree
177+
178+
// Calling preOrderIterative() function by passing a root node,
179+
// and storing the preorder traversal in result.
180+
result = binaryTree.preOrderIterative(root);
181+
182+
// Self-testing the result using `assert`
183+
for(int i = 0; i < result.size(); i++)
184+
assert(actual_result[i] == result[i]);
185+
186+
// Printing the result storing preorder.
187+
std::cout<< "\nPreOrder Traversal Is : "<< std::endl;
188+
for(auto i: result) {
189+
std::cout<< i<< " ";
190+
}
191+
}
192+
193+
/**
194+
* @brief Test the computed postorder with the actual postorder.
195+
* @param binaryTree instance of BinaryTree class
196+
* @param root head/root node of a tree
197+
*/
198+
static void test2(others::iterative_tree_traversals::BinaryTree binaryTree, others::iterative_tree_traversals::Node *root){
199+
std::vector<int64_t> actual_result{4, 5, 2, 3, 1};
200+
std::vector<int64_t> result; ///< result stores the postorder traversal of the binary tree.
201+
202+
// Calling postOrderIterative() function by passing a root node,
203+
// and storing the postorder traversal in result.
204+
result = binaryTree.postOrderIterative(root);
205+
206+
// Self-testing the result using `assert`
207+
for(int i = 0; i < result.size(); i++)
208+
assert(actual_result[i] == result[i]);
209+
210+
// Printing the result storing postorder.
211+
std::cout<< "\nPostOrder Traversal Is : "<< std::endl;
212+
for(auto i: result) {
213+
std::cout<< i<< " ";
214+
}
215+
}
216+
217+
/**
218+
* @brief Test the computed inorder with the actual inorder.
219+
* @param binaryTree instance of BinaryTree class
220+
* @param root head/root node of a tree
221+
*/
222+
static void test3(others::iterative_tree_traversals::BinaryTree binaryTree, others::iterative_tree_traversals::Node *root){
223+
std::vector<int64_t> actual_result{4, 2, 5, 1, 3};
224+
std::vector<int64_t> result; ///< result stores the inorder traversal of the binary tree.
225+
226+
// Calling inOrderIterative() function by passing a root node,
227+
// and storing the inorder traversal in result.
228+
result = binaryTree.inOrderIterative(root);
229+
230+
// Self-testing the result using `assert`
231+
for(int i = 0; i < result.size(); i++)
232+
assert(actual_result[i] == result[i]);
233+
234+
// Printing the result storing inorder.
235+
std::cout<< "\nInOrder Traversal Is : "<< std::endl;
236+
for(auto i: result) {
237+
std::cout<< i<< " ";
238+
}
239+
}
240+
241+
/**
242+
* @brief Test the computed preorder with the actual preorder on negative value.
243+
* @param binaryTree instance of BinaryTree class
244+
* @param root head/root node of a tree
245+
*/
246+
static void test4(others::iterative_tree_traversals::BinaryTree binaryTree, others::iterative_tree_traversals::Node *root){
247+
std::vector<int64_t> actual_result{-1, -2, -4, -5, -3};
248+
std::vector<int64_t> result; ///< result stores the preorder traversal of the binary tree
249+
250+
// Calling preOrderIterative() function by passing a root node,
251+
// and storing the preorder traversal in result.
252+
result = binaryTree.preOrderIterative(root);
253+
254+
// Self-testing the result using `assert`
255+
for(int i = 0; i < result.size(); i++)
256+
assert(actual_result[i] == result[i]);
257+
258+
// Printing the result storing preorder.
259+
std::cout<< "\nPreOrder Traversal Is : "<< std::endl;
260+
for(auto i: result) {
261+
std::cout<< i<< " ";
262+
}
263+
}
264+
265+
/**
266+
* @brief Test the computed postorder with the actual postorder on negative value.
267+
* @param binaryTree instance of BinaryTree class
268+
* @param root head/root node of a tree
269+
*/
270+
static void test5(others::iterative_tree_traversals::BinaryTree binaryTree, others::iterative_tree_traversals::Node *root){
271+
std::vector<int64_t> actual_result{-4, -5, -2, -3, -1};
272+
std::vector<int64_t> result; ///< result stores the postorder traversal of the binary tree.
273+
274+
// Calling postOrderIterative() function by passing a root node,
275+
// and storing the postorder traversal in result.
276+
result = binaryTree.postOrderIterative(root);
277+
278+
// Self-testing the result using `assert`
279+
for(int i = 0; i < result.size(); i++)
280+
assert(actual_result[i] == result[i]);
281+
282+
// Printing the result storing postorder.
283+
std::cout<< "\nPostOrder Traversal Is : "<< std::endl;
284+
for(auto i: result) {
285+
std::cout<< i<< " ";
286+
}
287+
}
288+
289+
/**
290+
* @brief Test the computed inorder with the actual inorder on negative value.
291+
* @param binaryTree instance of BinaryTree class
292+
* @param root head/root node of a tree
293+
*/
294+
static void test6(others::iterative_tree_traversals::BinaryTree binaryTree, others::iterative_tree_traversals::Node *root){
295+
std::vector<int64_t> actual_result{-4, -2, -5, -1, -3};
296+
std::vector<int64_t> result; ///< result stores the inorder traversal of the binary tree.
297+
298+
// Calling inOrderIterative() function by passing a root node,
299+
// and storing the inorder traversal in result.
300+
result = binaryTree.inOrderIterative(root);
301+
302+
// Self-testing the result using `assert`
303+
for(int i = 0; i < result.size(); i++)
304+
assert(actual_result[i] == result[i]);
305+
306+
// Printing the result storing inorder.
307+
std::cout<< "\nInOrder Traversal Is : "<< std::endl;
308+
for(auto i: result) {
309+
std::cout<< i<< " ";
310+
}
311+
}
312+
313+
/**
314+
* @brief Main function
315+
* @returns 0 on exit
316+
*/
317+
int main() {
318+
// Creating a tree with the following structure,
319+
/*
320+
1
321+
/ \
322+
2 3
323+
/ \
324+
4 5
325+
*/
326+
327+
others::iterative_tree_traversals::BinaryTree binaryTree; ///< instace of BinaryTree, used to access its members functions.
328+
others::iterative_tree_traversals::Node *root = binaryTree.createNewNode(1);
329+
root->left = binaryTree.createNewNode(2);
330+
root->right = binaryTree.createNewNode(3);
331+
root->left->left = binaryTree.createNewNode(4);
332+
root->left->right = binaryTree.createNewNode(5);
333+
334+
std::cout<< "\n| Tests for positive data value |"<< std::endl;
335+
test1(binaryTree, root); // run preorder-iterative test
336+
std::cout<< "\nPre-order test Passed!"<< std::endl;
337+
338+
test2(binaryTree, root); // run postorder-iterative test
339+
std::cout<< "\nPost-order test Passed!"<< std::endl;
340+
341+
test3(binaryTree, root); // run inorder-iterative test
342+
std::cout<< "\nIn-order test Passed!"<< std::endl;
343+
344+
// Modifying tree for negative values.
345+
root->data = -1;
346+
root->left->data = -2;
347+
root->right->data = -3;
348+
root->left->left->data = -4;
349+
root->left->right->data = -5;
350+
351+
std::cout<< "\n| Tests for negative data values |"<< std::endl;
352+
test4(binaryTree, root); // run preorder-iterative test on negative values
353+
std::cout<< "\nPre-order test on-negative value Passed!"<< std::endl;
354+
355+
test5(binaryTree, root); // run postorder-iterative test on negative values
356+
std::cout<< "\nPost-order test on-negative value Passed!"<< std::endl;
357+
358+
test6(binaryTree, root); // run inorder-iterative test on negative values
359+
std::cout<< "\nIn-order test on-negative value Passed!"<< std::endl;
360+
361+
return 0;
362+
}

0 commit comments

Comments
 (0)