Last active
September 17, 2018 20:15
-
-
Save JKomskis/d1486612ca19252116ff26e0de0cbbb6 to your computer and use it in GitHub Desktop.
Twelve ways to traverse a binary tree
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#define DEBUG | |
#include "Binary_Tree.h" | |
int compare_int(int a, int b){ | |
if(a < b){ | |
return -1; | |
} else if (a == b){ | |
return 0; | |
} else { | |
return 1; | |
} | |
} | |
void print(int n){ | |
std::cout << n << " "; | |
} | |
int main(){ | |
Binary_Tree<int, compare_int> tree; | |
tree.insert(6); | |
tree.insert(5); | |
tree.insert(7); | |
tree.insert(1); | |
tree.insert(2); | |
tree.insert(9); | |
tree.insert(10); | |
tree.insert(3); | |
tree.insert(8); | |
tree.insert(4); | |
tree.print(std::cout); | |
std::cout << "-----Preorder-----" << std::endl; | |
std::cout << "Recursive (Centralized):\t"; | |
std::cout << "[ "; | |
tree.preorder_recursive_centralized(print); | |
std::cout << "]" << std::endl; | |
std::cout << "Recursive (Decentralized):\t"; | |
std::cout << "[ "; | |
tree.preorder_recursive_decentralized(print); | |
std::cout << "]" << std::endl; | |
std::cout << "Iterative (Stack Based):\t"; | |
std::cout << "[ "; | |
tree.preorder_iterative_stack_based(print); | |
std::cout << "]" << std::endl; | |
std::cout << "Iterative (Stack Free):\t\t"; | |
std::cout << "[ "; | |
tree.preorder_iterative_stack_free(print); | |
std::cout << "]" << std::endl; | |
std::cout << "-----Inorder-----" << std::endl; | |
std::cout << "Recursive (Centralized):\t"; | |
std::cout << "[ "; | |
tree.inorder_recursive_centralized(print); | |
std::cout << "]" << std::endl; | |
std::cout << "Recursive (Decentralized):\t"; | |
std::cout << "[ "; | |
tree.inorder_recursive_decentralized(print); | |
std::cout << "]" << std::endl; | |
std::cout << "Iterative (Stack Based):\t"; | |
std::cout << "[ "; | |
tree.inorder_iterative_stack_based(print); | |
std::cout << "]" << std::endl; | |
std::cout << "Iterative (Stack Free):\t\t"; | |
std::cout << "[ "; | |
tree.inorder_iterative_stack_free(print); | |
std::cout << "]" << std::endl; | |
std::cout << "-----Postorder-----" << std::endl; | |
std::cout << "Recursive (Centralized):\t"; | |
std::cout << "[ "; | |
tree.postorder_recursive_centralized(print); | |
std::cout << "]" << std::endl; | |
std::cout << "Recursive (Decentralized):\t"; | |
std::cout << "[ "; | |
tree.postorder_recursive_decentralized(print); | |
std::cout << "]" << std::endl; | |
std::cout << "Iterative (Stack Based):\t"; | |
std::cout << "[ "; | |
tree.postorder_iterative_stack_based(print); | |
std::cout << "]" << std::endl; | |
std::cout << "-----Levelorder-----" << std::endl; | |
std::cout << "Iterative (Queue Based):\t"; | |
std::cout << "[ "; | |
tree.levelorder(print); | |
std::cout << "]" << std::endl; | |
return 0; | |
} | |
/* | |
* Output: | |
* 6 Left: 5 Right: 7 | |
* 5 Left: 1 | |
* 1 Right: 2 | |
* 2 Right: 3 | |
* 3 Right: 4 | |
* 4 | |
* 7 Right: 9 | |
* 9 Left: 8 Right: 10 | |
* 8 | |
* 10 | |
* -----Preorder----- | |
* Recursive (Centralized): [ 6 5 1 2 3 4 7 9 8 10 ] | |
* Recursive (Decentralized): [ 6 5 1 2 3 4 7 9 8 10 ] | |
* Iterative (Stack Based): [ 6 5 1 2 3 4 7 9 8 10 ] | |
* Iterative (Stack Free): [ 6 5 1 2 3 4 7 9 8 10 ] | |
* -----Inorder----- | |
* Recursive (Centralized): [ 1 2 3 4 5 6 7 8 9 10 ] | |
* Recursive (Decentralized): [ 1 2 3 4 5 6 7 8 9 10 ] | |
* Iterative (Stack Based): [ 1 2 3 4 5 6 7 8 9 10 ] | |
* Iterative (Stack Free): [ 1 2 3 4 5 6 7 8 9 10 ] | |
* -----Postorder----- | |
* Recursive (Centralized): [ 4 3 2 1 5 8 10 9 7 6 ] | |
* Recursive (Decentralized): [ 4 3 2 1 5 8 10 9 7 6 ] | |
* Iterative (Stack Based): [ 4 3 2 1 5 8 10 9 7 6 ] | |
* -----Levelorder----- | |
* Iterative (Queue Based): [ 6 5 7 1 9 2 8 10 3 4 ] | |
*/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef _BINARY_TREE_H_ | |
#define _BINARY_TREE_H_ | |
#include <stack> | |
#include <queue> | |
template <typename T> | |
class Node{ | |
public: | |
T data; | |
Node *left; | |
Node *right; | |
Node(T data); | |
~Node(); | |
void preorder(void (*process)(T)); | |
void inorder(void (*process)(T)); | |
void postorder(void (*process)(T)); | |
}; | |
template <typename T> | |
Node<T>::Node(T data) : data(data), left(nullptr), right(nullptr){} | |
template <typename T> | |
Node<T>::~Node(){ | |
if(left) | |
delete left; | |
if(right) | |
delete right; | |
} | |
template <typename T> | |
void Node<T>::preorder(void (*process)(T)){ | |
process(data); | |
if(left) left->preorder(process); | |
if(right) right->preorder(process); | |
} | |
template <typename T> | |
void Node<T>::inorder(void (*process)(T)){ | |
if(left) left->inorder(process); | |
process(data); | |
if(right) right->inorder(process); | |
} | |
template <typename T> | |
void Node<T>::postorder(void (*process)(T)){ | |
if(left) left->postorder(process); | |
if(right) right->postorder(process); | |
process(data); | |
} | |
template <typename T, int (*F)(T,T)> | |
class Binary_Tree{ | |
Node<T> *root; | |
//preorder | |
void do_preorder_recursive_centralized(void (*process)(T), Node<T> *node); | |
//inorder | |
void do_inorder_recursive_centralized(void (*process)(T), Node<T> *node); | |
//postorder | |
void do_postorder_recursive_centralized(void (*process)(T), Node<T> *node); | |
public: | |
Binary_Tree<T, F>(); | |
~Binary_Tree<T, F>(); | |
void insert(T new_value); | |
//preorder | |
void preorder_recursive_centralized(void (*process)(T)); | |
void preorder_recursive_decentralized(void (*process)(T)); | |
void preorder_iterative_stack_based(void (*process)(T)); | |
void preorder_iterative_stack_free(void (*process)(T)); | |
//inorder | |
void inorder_recursive_centralized(void (*process)(T)); | |
void inorder_recursive_decentralized(void (*process)(T)); | |
void inorder_iterative_stack_based(void (*process)(T)); | |
void inorder_iterative_stack_free(void (*process)(T)); | |
//postorder | |
void postorder_recursive_centralized(void (*process)(T)); | |
void postorder_recursive_decentralized(void (*process)(T)); | |
void postorder_iterative_stack_based(void (*process)(T)); | |
//levelorder | |
void levelorder(void (*process)(T)); | |
#ifdef DEBUG | |
std::ostream& print(std::ostream &out); | |
std::ostream& do_print(std::ostream &out, Node<T> *curr); | |
#endif | |
}; | |
template <typename T, int (*F)(T,T)> | |
Binary_Tree<T,F>::Binary_Tree() : root(nullptr){} | |
template <typename T, int (*F)(T,T)> | |
Binary_Tree<T,F>::~Binary_Tree(){ | |
delete root; | |
} | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T,F>::insert(T new_value){ | |
if(!root){ | |
root = new Node<T>(new_value); | |
return; | |
} | |
Node<T> *curr = root; | |
while(curr){ | |
if(F(new_value, curr->data) < 0) { | |
if(curr->left == nullptr){ | |
curr->left = new Node<T>(new_value); | |
return; | |
} else { | |
curr = curr->left; | |
} | |
} else { | |
if(curr->right == nullptr){ | |
curr->right = new Node<T>(new_value); | |
return; | |
} else { | |
curr = curr->right; | |
} | |
} | |
} | |
} | |
//------------------------- | |
// Preorder | |
//------------------------- | |
//centralized recursive | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T, F>::preorder_recursive_centralized( void (*process)(T) ){ | |
if(root) do_preorder_recursive_centralized(process, root); | |
} | |
template <typename T, int(*F)(T,T)> | |
void Binary_Tree<T, F>::do_preorder_recursive_centralized( void (*process)(T), Node<T> *node ){ | |
process(node->data); | |
if(node->left) do_preorder_recursive_centralized(process, node->left); | |
if(node->right) do_preorder_recursive_centralized(process, node->right); | |
} | |
//decentralized recursive | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T, F>::preorder_recursive_decentralized(void (*process)(T)){ | |
if(root) root->preorder(process); | |
} | |
//stack-based iterative | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T, F>::preorder_iterative_stack_based(void (*process)(T)){ | |
std::stack<Node<T>*> stack; | |
stack.push(root); | |
while(!stack.empty()){ | |
Node<T> *curr = stack.top(); | |
stack.pop(); | |
process(curr->data); | |
if(curr->right) stack.push(curr->right); | |
if(curr->left) stack.push(curr->left); | |
} | |
} | |
//stack-free iterative | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T, F>::preorder_iterative_stack_free(void (*process)(T)){ | |
Node<T> *anchor = root; | |
while(anchor){ | |
if(!anchor->left){ | |
process(anchor->data); | |
anchor = anchor->right; | |
} else { | |
Node<T>* iop = anchor->left; | |
while( iop && iop->right && ( F(iop->right->data, anchor->data) != 0 ) ) iop = iop->right; | |
if(iop->right != anchor){ | |
process(anchor->data); | |
iop->right = anchor; | |
anchor = anchor->left; | |
} else { | |
iop->right = nullptr; | |
anchor = anchor->right; | |
} | |
} | |
} | |
} | |
//------------------------- | |
// Inorder | |
//------------------------- | |
//centralized recursive | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T, F>::inorder_recursive_centralized( void (*process)(T) ){ | |
if(root) do_inorder_recursive_centralized(process, root); | |
} | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T, F>::do_inorder_recursive_centralized( void (*process)(T), Node<T> *node){ | |
if(node->left) do_inorder_recursive_centralized(process, node->left); | |
process(node->data); | |
if(node->right) do_inorder_recursive_centralized(process, node->right); | |
} | |
//decentralzied recursive | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T, F>::inorder_recursive_decentralized(void (*process)(T)){ | |
if(root) root->inorder(process); | |
} | |
//stack-based iterative | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T,F>::inorder_iterative_stack_based(void (*process)(T)){ | |
std::stack<Node<T>*> stack; | |
Node<T>* curr = root; | |
while(curr || !stack.empty()){ | |
if(curr){ | |
stack.push(curr); | |
curr = curr->left; | |
} else { | |
curr = stack.top(); | |
process(curr->data); | |
stack.pop(); | |
curr = curr->right; | |
} | |
} | |
} | |
//stack-free iterative | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T, F>::inorder_iterative_stack_free(void (*process)(T)){ | |
Node<T> *anchor = root; | |
while(anchor){ | |
if(!anchor->left){ | |
process(anchor->data); | |
anchor = anchor->right; | |
} else { | |
Node<T> *iop = anchor->left; | |
while( iop && iop->right && (F(iop->right->data, anchor->data) != 0) ) iop = iop->right; | |
if(iop->right != anchor){ | |
iop->right = anchor; | |
anchor = anchor->left; | |
} else { | |
process(anchor->data); | |
iop->right = nullptr; | |
anchor = anchor->right; | |
} | |
} | |
} | |
} | |
//------------------------- | |
// Postorder | |
//------------------------- | |
//centralized | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T, F>::postorder_recursive_centralized( void (*process)(T) ){ | |
if(root) do_postorder_recursive_centralized(process, root); | |
} | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T, F>::do_postorder_recursive_centralized( void (*process)(T), Node<T> *node ){ | |
if(node->left) do_postorder_recursive_centralized( process, node->left); | |
if(node->right) do_postorder_recursive_centralized( process, node->right); | |
process(node->data); | |
} | |
//decentralized | |
template <typename T, int (*F)(T,T)> | |
void Binary_Tree<T, F>::postorder_recursive_decentralized(void (*process)(T)){ | |
if(root) root->postorder(process); | |
} | |
//stack-based iterative | |
template <typename T, int(*F)(T,T)> | |
void Binary_Tree<T, F>::postorder_iterative_stack_based(void (*process)(T)){ | |
std::stack<Node<T>*> stack; | |
stack.push(root); | |
Node<T> *curr = nullptr; | |
Node<T> *prev = nullptr; | |
while(!stack.empty()){ | |
curr = stack.top(); | |
//traversing downwards | |
if(prev == nullptr || prev->left == curr || prev->right == curr){ | |
if(curr->left){ | |
stack.push(curr->left); | |
} | |
else if(curr->right){ | |
stack.push(curr->right); | |
} | |
//traversing upwards on the left side | |
} else if (curr->left == prev){ | |
if(curr->right){ | |
stack.push(curr->right); | |
} | |
//traversing upwards on the right side | |
} else { | |
process(curr->data); | |
stack.pop(); | |
} | |
prev = curr; | |
} | |
} | |
//------------------------- | |
// Levelorder | |
//------------------------- | |
template <typename T, int(*F)(T,T)> | |
void Binary_Tree<T, F>::levelorder(void (*process)(T)){ | |
std::queue<Node<T>*> queue; | |
queue.push(root); | |
while(!queue.empty()){ | |
Node<T>* node = queue.front(); | |
queue.pop(); | |
process(node->data); | |
if(node->left) queue.push(node->left); | |
if(node->right) queue.push(node->right); | |
} | |
} | |
#ifdef DEBUG | |
template <typename T, int (*F)(T,T)> | |
std::ostream& Binary_Tree<T, F>::print(std::ostream &out){ | |
return do_print(out, root); | |
} | |
template <typename T, int (*F)(T,T)> | |
std::ostream& Binary_Tree<T, F>::do_print(std::ostream &out, Node<T> *node){ | |
//print the current node | |
out << node->data; | |
if(node->left) out << " Left: " << node->left->data; | |
if(node->right) out << " Right: " << node->right->data; | |
out << std::endl; | |
//recursively print node's children | |
if(node->left) do_print(out, node->left); | |
if(node->right) do_print(out, node->right); | |
return out; | |
} | |
#endif | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment