Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Boundary Level order traversal of a Binary Tree
In this problem, we will traverse each boundary of the given binary tree in the given order.
We will use the recursive approach to traverse each boundary of the binary tree one by one. However, we will also learn the iterative approach using a stack to traverse the binary tree's boundary and increase the code's performance.
Problem Statement
We have given a binary tree, and we need to traverse each boundary of the tree in the given order.
Traverse left boundary in top to bottom manner.
Traverse bottom boundary from left to right.
Traverse the right boundary from bottom to top.
Sample Examples
Input
4 / \ 8 9
Output
4, 8, 9
Explanation
We traverse the boundary of the tree.
Input
9
/ \
6 8
/ \
10 53
/ \
12 3
Output
9, 6, 10, 12, 3, 8,
Explanation
We can consider the 9, 6, 10, and 12 into the left boundary. We can consider the 10, 12, and 3 as the bottom boundary. We can consider the 3, 8, and 9 as the right boundary. Here, we have printed all boundary elements once.
Approach 1
In this approach, we will write 3 recursive functions to traverse each node of the left, bottom, and right boundaries.
Algorithm
Step 1 ? Create a treenode class containing the integer variable, left and right pointers, and constructor to initialize the node.
Step 2 ? In the main() method, create a binary tree and execute the traverseBoundary() function.
Step 3 ? In the traverseBoundary() function, execute the return statement if the head is null. Otherwise, print the value of the head node.
Step 4 ? Call the showLeft() function for the left subtree to traverse the left boundary.
Step 4.1 ? In the showLeft() function, if the head is null or doesn't contain a child node, return from the function.
Step 4.2 ? If the left child exists, print its value, and call the showLeft() function by passing it as a parameter. Otherwise, print the value of the right child node, and execute the showLeft() function for the right child node.
Step 5 ? Execute the showBottom() function to show the boundary of the left and right subtree.
Step 5.1 ? In the showBottom() function, execute the return statement if the head is null.
Step 5.2 ? Print its value if the current node is a leaf noue.
Step 5.3 ? Execute the showBottom() function for the left and right child nodes.
Step 6 ? Execute the showRight() function to traverse the right boundary.
Step 6.1 ? In the showRIght() function, execute the return if the head is null or contains no child.
Step 6.2 ? If the right node is not null, execute the showRight() function for the right subtree, and print the value of the right node. Here, we print the node value after the function call as we need to traverse the tree from bottom to top.
Step 6.3 ? If the right child not exists but the left child exists, make a recursive call for the left child, and print its value afterward.
Example
#include <bits/stdc++.h>
using namespace std;
class treenode {
public:
int val;
treenode *left, *right;
// constructor
treenode() {
left = NULL;
right = NULL;
}
};
void showBottom(treenode *head) {
// Base case
if (head == NULL)
return;
// When head node is a leaf node
if ((head->left) == NULL && (head->right) == NULL)
cout << head->val << " ";
// Traverse left subtree
showBottom(head->left);
// Traverse the right subtree
showBottom(head->right);
}
void showLeft(treenode *head) {
if (head == NULL && (head->left == NULL && head->right == NULL))
return;
// When the left child exists
if (head->left != NULL) {
cout << head->val << " ";
// Recursive function call
showLeft(head->left);
} else if (head->right != NULL) {
// When the left child not exists
cout << head->val << " ";
showLeft(head->right);
}
}
void showRight(treenode *head) {
// Base case
if (head == NULL || (head->left == NULL && head->right == NULL))
return;
// When a right child is present
if (head->right != NULL) {
showRight(head->right);
cout << head->val << " ";
}
// When the right child is not present
else if (head->left != NULL) {
showRight(head->left);
cout << head->val << " ";
}
}
void traverseBoundary(treenode *head) {
// When the tree is null
if (head == NULL)
return;
// pRoot node
cout << head->val << " ";
// Showing left boundary
showLeft(head->left);
// Showing the bottom of the left subtree
showBottom(head->left);
// Showing the bottom of the right subtree
showBottom(head->right);
// Show the right boundary
showRight(head->right);
}
treenode *createNewNode(int val) {
treenode *temp = new treenode();
temp->val = val;
return temp;
}
int main() {
treenode *head = createNewNode(9);
head->left = createNewNode(6);
head->right = createNewNode(8);
head->left->left = createNewNode(10);
head->left->right = createNewNode(53);
head->left->right->left = createNewNode(12);
head->left->right->right = createNewNode(3);
traverseBoundary(head);
}
Output
9 6 10 12 3 8
Time complexity ? O(N) to traverse each node.
Space complexity ? O(H) for recursion stack.
Approach 2
In this approach, we will use the stack data structure to traverse each boundary of the binary tree.
Algorithm
Step 1 ? When the head is not null, follow the below steps.
Step 2 ? If the head doesn't contain any child node, print its value and return from the function.
Step 3 ? Define the l_nodes list. Traverse each left node of the tree and push into the l_nodes.
Step 4 ? Define stack_1 and stack_2 to store all nodes and leaft nodes respectively. Insert the head node in stack1.
Step 5 ? Now, make iterations until stack1 becomes empty.
Step 5.1 ? In the loop, pop the node from the stack. If their child exists, insert child elements in the stack. If the child not exists, insert the node into the stack_2.
Step 6 ? Now, insert all elements of stack_2 into the l_nodes.
Step 7 ? Now, define the rightNode list, traverse all right nodes, and insert them into the list. Also, reverse the rightNodes list.
Step 8 ? Append all nodes of rightNodes into the l_nodes list, and print elements of l_nodes.
Example
#include <bits/stdc++.h>
using namespace std;
class treenode {
public:
int val;
treenode *left, *right;
// constructor
treenode() {
left = NULL;
right = NULL;
}
};
void traverseBoundary(treenode *head) {
if (head != NULL) {
// For a tree with a single node
if ((head->left == NULL) && (head->right == NULL)) {
cout << head->val << endl;
return;
}
vector<treenode *> l_nodes; // To store node order
l_nodes.push_back(head);
treenode *leftNode = head->left; // For left boundary traversal
// Insert left noes in the list
while (leftNode->left) {
l_nodes.push_back(leftNode);
leftNode = leftNode->left;
}
stack<treenode *> stack_1; // To store all nodes
stack<treenode *> stack_2; // For storing leaf nodes
stack_1.push(head); // Insert head
while (!stack_1.empty()) {
treenode *temp = stack_1.top();
stack_1.pop();
// Insert left child in a stack
if (temp->left)
stack_1.push(temp->left);
// Insert right child in the stack
if (temp->right)
stack_1.push(temp->right);
// For leaf node
else if (!temp->left && !temp->right)
stack_2.push(temp);
}
// Show all leaf nodes
while (!stack_2.empty()) {
l_nodes.push_back(stack_2.top());
stack_2.pop();
}
vector<treenode *> rightNodes; // Right boundary
treenode *r_node = head->right;
while (r_node->right) {
rightNodes.push_back(r_node);
r_node = r_node->right;
}
reverse(rightNodes.begin(), rightNodes.end()); // Revere right node order
l_nodes.insert(l_nodes.end(), rightNodes.begin(), rightNodes.end()); // Merge two list
// Printing the boundary traversal
for (auto p : l_nodes) {
cout << p->val << " ";
}
cout << endl;
return;
}
}
treenode *createNewNode(int val) {
treenode *temp = new treenode();
temp->val = val;
return temp;
}
int main() {
treenode *head = createNewNode(9);
head->left = createNewNode(6);
head->right = createNewNode(8);
head->left->left = createNewNode(10);
head->left->right = createNewNode(53);
head->left->right->left = createNewNode(12);
head->left->right->right = createNewNode(3);
traverseBoundary(head);
}
Output
9 6 10 12 3 8
Time complexity ? O(N)
Space complexity ? O(N)
The iterative approach using the stack is faster than the recursive approach but consumes more memory, which might not be suitable for handling large data.