
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.