Given a Binary Tree and a key, write a function that prints all the ancestors of the key in the given binary tree.
For example, if the given tree is following Binary Tree and the key is 7, then your function should print 4, 2, and 1.
1
/ \
2 3
/ \
4 5
/
7
Thanks to Mike, Sambasiva and wgpshashank for their contribution.
C++
#include<bits/stdc++.h>
using namespace std;
struct node
{
int data;
struct node* left;
struct node* right;
};
bool printAncestors( struct node *root, int target)
{
if (root == NULL)
return false ;
if (root->data == target)
return true ;
if ( printAncestors(root->left, target) ||
printAncestors(root->right, target) )
{
cout << root->data << " " ;
return true ;
}
return false ;
}
struct node* newnode( int data)
{
struct node* node = ( struct node*)
malloc ( sizeof ( struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return (node);
}
int main()
{
struct node *root = newnode(1);
root->left = newnode(2);
root->right = newnode(3);
root->left->left = newnode(4);
root->left->right = newnode(5);
root->left->left->left = newnode(7);
printAncestors(root, 7);
getchar ();
return 0;
}
|
Java
class Node
{
int data;
Node left, right, nextRight;
Node( int item)
{
data = item;
left = right = nextRight = null ;
}
}
class BinaryTree
{
Node root;
boolean printAncestors(Node node, int target)
{
if (node == null )
return false ;
if (node.data == target)
return true ;
if (printAncestors(node.left, target)
|| printAncestors(node.right, target))
{
System.out.print(node.data + " " );
return true ;
}
return false ;
}
public static void main(String args[])
{
BinaryTree tree = new BinaryTree();
tree.root = new Node( 1 );
tree.root.left = new Node( 2 );
tree.root.right = new Node( 3 );
tree.root.left.left = new Node( 4 );
tree.root.left.right = new Node( 5 );
tree.root.left.left.left = new Node( 7 );
tree.printAncestors(tree.root, 7 );
}
}
|
Python3
class Node:
def __init__( self , data):
self .data = data
self .left = None
self .right = None
def printAncestors(root, target):
if root = = None :
return False
if root.data = = target:
return True
if (printAncestors(root.left, target) or
printAncestors(root.right, target)):
print (root.data,end = ' ' )
return True
return False
root = Node( 1 )
root.left = Node( 2 )
root.right = Node( 3 )
root.left.left = Node( 4 )
root.left.right = Node( 5 )
root.left.left.left = Node( 7 )
printAncestors(root, 7 )
|
C#
using System;
public class Node
{
public int data;
public Node left, right, nextRight;
public Node( int item)
{
data = item;
left = right = nextRight = null ;
}
}
public class BinaryTree
{
public Node root;
public virtual bool printAncestors(Node node, int target)
{
if (node == null )
{
return false ;
}
if (node.data == target)
{
return true ;
}
if (printAncestors(node.left, target)
|| printAncestors(node.right, target))
{
Console.Write(node.data + " " );
return true ;
}
return false ;
}
public static void Main( string [] args)
{
BinaryTree tree = new BinaryTree();
tree.root = new Node(1);
tree.root.left = new Node(2);
tree.root.right = new Node(3);
tree.root.left.left = new Node(4);
tree.root.left.right = new Node(5);
tree.root.left.left.left = new Node(7);
tree.printAncestors(tree.root, 7);
}
}
|
Javascript
<script>
class Node
{
constructor(item) {
this .data = item;
this .left = null ;
this .right = null ;
this .nextRight = null ;
}
}
let root;
function printAncestors(node, target)
{
if (node == null )
return false ;
if (node.data == target)
return true ;
if (printAncestors(node.left, target)
|| printAncestors(node.right, target))
{
document.write(node.data + " " );
return true ;
}
return false ;
}
root = new Node(1);
root.left = new Node(2);
root.right = new Node(3);
root.left.left = new Node(4);
root.left.right = new Node(5);
root.left.left.left = new Node(7);
printAncestors(root, 7);
</script>
|
Time Complexity: O(n) where n is the number of nodes in the given Binary Tree.
Auxiliary Space: O(h) where h is the height of given Binary Tree
Another Approach :
An alternative approach to solving this problem is by using an iterative approach with a stack data structure.
1. We start by creating an empty stack to store the nodes.
2. We enter a while loop that continues until the current node is NULL and the stack is empty.
3. Inside the loop, we traverse the left subtree of the current node, pushing each encountered node onto the stack until we reach a leaf node or find the target node.
4. If we find the target node, we break out of the loop.
5. If the current node is NULL and the stack is not empty, it means we have finished processing the left subtree and need to backtrack to the parent nodes.
6. We check if the right child of the top node on the stack is NULL or if it has already been processed. If so, it indicates that we have finished processing that node and its subtree.
7. In such cases, we print the top node’s data (which represents an ancestor) and pop it from the stack.
8. We continue this process until we find a node whose right child has not been processed.
9. Once we finish processing the left subtree and backtrack to the current node’s right child, we update the current node accordingly.
a) If the stack is not empty, we set the current node to the right child of the top node on the stack.
b) If the stack is empty, it means we have finished traversing the entire tree, and we set the current node to NULL.
10. Finally, if the stack is not empty, we print the contents of the stack, which represents the ancestors of the target node.
11. If the stack is empty, it means the target node was not found, and we return false.
This iterative approach simulates the recursive approach by using a stack to keep track of the nodes and their respective subtrees as we traverse the tree. It eliminates the need for recursive function calls and utilizes the stack to manage the backtracking process.
Both the recursive and iterative approaches achieve the same goal of finding and printing the ancestors of a given node in a binary tree.
C++
#include<bits/stdc++.h>
using namespace std;
struct node
{
int data;
struct node* left;
struct node* right;
};
bool printAncestors( struct node *root, int target)
{
stack<node*> st;
while (root || !st.empty()) {
while (root && root->data != target) {
st.push(root);
root = root->left;
}
if (root && root->data == target)
break ;
if (!st.empty() && st.top()->right == NULL) {
root = st.top();
st.pop();
while (!st.empty() && st.top()->right == root) {
root = st.top();
st.pop();
}
}
root = (!st.empty()) ? st.top()->right : NULL;
}
if (!st.empty()) {
while (!st.empty()) {
cout << st.top()->data << " " ;
st.pop();
}
return true ;
}
return false ;
}
struct node* newnode( int data)
{
struct node* node = ( struct node*) malloc ( sizeof ( struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return (node);
}
int main()
{
struct node *root = newnode(1);
root->left = newnode(2);
root->right = newnode(3);
root->left->left = newnode(4);
root->left->right = newnode(5);
root->left->left->left = newnode(7);
printAncestors(root, 7);
return 0;
}
|
Java
import java.util.Stack;
class Node {
int data;
Node left;
Node right;
Node( int data) {
this .data = data;
left = null ;
right = null ;
}
}
public class GFG {
public static boolean printAncestors(Node root, int target) {
Stack<Node> stack = new Stack<>();
while (root != null || !stack.isEmpty()) {
while (root != null && root.data != target) {
stack.push(root);
root = root.left;
}
if (root != null && root.data == target) {
break ;
}
if (!stack.isEmpty() && stack.peek().right == null ) {
root = stack.pop();
while (!stack.isEmpty() && stack.peek().right == root) {
root = stack.pop();
}
}
root = !stack.isEmpty() ? stack.peek().right : null ;
}
if (!stack.isEmpty()) {
while (!stack.isEmpty()) {
System.out.print(stack.pop().data + " " );
}
return true ;
}
return false ;
}
public static void main(String[] args) {
Node root = new Node( 1 );
root.left = new Node( 2 );
root.right = new Node( 3 );
root.left.left = new Node( 4 );
root.left.right = new Node( 5 );
root.left.left.left = new Node( 7 );
printAncestors(root, 7 );
}
}
|
Python3
class Node:
def __init__( self , data):
self .data = data
self .left = None
self .right = None
def print_ancestors(root, target):
st = []
while root or st:
while root and root.data ! = target:
st.append(root)
root = root.left
if root and root.data = = target:
break
if st and not st[ - 1 ].right:
root = st.pop()
while st and st[ - 1 ].right = = root:
root = st.pop()
root = st[ - 1 ].right if st else None
if st:
while st:
print (st[ - 1 ].data, end = ' ' )
st.pop()
return True
return False
def new_node(data):
return Node(data)
root = new_node( 1 )
root.left = new_node( 2 )
root.right = new_node( 3 )
root.left.left = new_node( 4 )
root.left.right = new_node( 5 )
root.left.left.left = new_node( 7 )
print_ancestors(root, 7 )
|
C#
using System;
using System.Collections.Generic;
public class Node
{
public int Data;
public Node Left;
public Node Right;
}
public class BinaryTree
{
public static bool PrintAncestors(Node root, int target)
{
Stack<Node> st = new Stack<Node>();
while (root != null || st.Count > 0)
{
while (root != null && root.Data != target)
{
st.Push(root);
root = root.Left;
}
if (root != null && root.Data == target)
break ;
if (st.Count > 0 && st.Peek().Right == null )
{
root = st.Pop();
while (st.Count > 0 && st.Peek().Right == root)
{
root = st.Pop();
}
}
root = (st.Count > 0) ? st.Peek().Right : null ;
}
if (st.Count > 0)
{
while (st.Count > 0)
{
Console.Write(st.Peek().Data + " " );
st.Pop();
}
return true ;
}
return false ;
}
public static Node NewNode( int data)
{
Node node = new Node
{
Data = data,
Left = null ,
Right = null
};
return node;
}
public static void Main()
{
Node root = NewNode(1);
root.Left = NewNode(2);
root.Right = NewNode(3);
root.Left.Left = NewNode(4);
root.Left.Right = NewNode(5);
root.Left.Left.Left = NewNode(7);
PrintAncestors(root, 7);
}
}
|
Javascript
class node {
constructor(data) {
this .data = data;
this .left = null ;
this .right = null ;
}
}
function printAncestors(root, target) {
let st = [];
while (root || st.length > 0) {
while (root && root.data != target) {
st.push(root);
root = root.left;
}
if (root && root.data == target)
break ;
if (st.length > 0 && st[st.length - 1].right == null ) {
root = st[st.length - 1];
st.pop();
while (st.length > 0 && st[st.length - 1].right == root) {
root = st[st.length - 1];
st.pop();
}
}
root = (st.length > 0) ? st[st.length - 1].right : null ;
}
if (st.length > 0) {
while (st.length > 0) {
console.log(st[st.length - 1].data + " " );
st.pop();
}
return true ;
}
return false ;
}
function newnode(data) {
return new node(data);
}
let root = newnode(1);
root.left = newnode(2);
root.right = newnode(3);
root.left.left = newnode(4);
root.left.right = newnode(5);
root.left.left.left = newnode(7);
printAncestors(root, 7);
|
- Time Complexity: O(n) where n is the number of nodes in the given Binary Tree.
- Auxiliary Space: O(h) where h is the height of given Binary Tree
Feeling lost in the world of random DSA topics, wasting time without progress? It's time for a change! Join our DSA course, where we'll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 geeks!
Last Updated :
20 Sep, 2023
Like Article
Save Article