Given a string str that contains a ternary expression which may be nested. The task is to convert the given ternary expression to a binary tree and return the root.
Examples:
Input: str = "a?b:c" Output: a b c a / \ b c The preorder traversal of the above tree is a b c. Input: str = "a?b?c:d:e" Output: a b c d e a / \ b e / \ c d
Approach: This is a stack-based approach to the given problem. Since the ternary operator has associativity from right-to-left, the string can be traversed from right to left. Take the letters one by one skipping the letters ‘?’ and ‘:’ as these letters are used to decide whether the current letter (alphabet [a to z]) will go into the stack or be used to pop the top 2 elements from the top of the stack to make them the children of the current letter which is then itself pushed into the stack. This forms the tree in a bottom-up manner and the last remaining element in the stack after the entire string is processed is the root of the tree.
Below is the implementation of the above approach:
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std;
// Node structure struct Node {
char data;
Node *left, *right;
}; // Function to create a new node Node* createNewNode( int data)
{ Node* node = new Node;
node->data = data;
node->left = NULL, node->right = NULL;
return node;
} // Function to print the preorder // traversal of the tree void preorder(Node* root)
{ if (root == NULL)
return ;
cout << root->data << " " ;
preorder(root->left);
preorder(root->right);
} // Function to convert the expression to a binary tree Node* convertExpression(string str) { stack<Node*> s;
// If the letter is the last letter of
// the string or is of the type :letter: or ?letter:
// we push the node pointer containing
// the letter to the stack
for ( int i = str.length() - 1; i >= 0;) {
if ((i == str.length() - 1)
|| (i != 0 && ((str[i - 1] == ':'
&& str[i + 1] == ':' )
|| (str[i - 1] == '?'
&& str[i + 1] == ':' )))) {
s.push(createNewNode(str[i]));
}
// If we do not push the current letter node to stack,
// it means the top 2 nodes in the stack currently are the
// left and the right children of the current node
// So pop these elements and assign them as the
// children of the current letter node and then
// push this node into the stack
else {
Node* lnode = s.top();
s.pop();
Node* rnode = s.top();
s.pop();
Node* node = createNewNode(str[i]);
node->left = lnode;
node->right = rnode;
s.push(node);
}
i -= 2;
}
// Finally, there will be only 1 element
// in the stack which will be the
// root of the binary tree
return s.top();
} // Driver code int main()
{ string str = "a?b?c:d:e" ;
// Convert expression
Node* root = convertExpression(str);
// Print the preorder traversal
preorder(root);
return 0;
} |
// Java implementation of the approach import java.util.*;
public class Main
{ // Class containing left and
// right child of current
// node and key value
static class Node {
public char data;
public Node left, right;
public Node( char data)
{
this .data = data;
left = right = null ;
}
}
// Function to create a new node
static Node createNewNode( char data)
{
Node node = new Node(data);
return node;
}
// Function to print the preorder
// traversal of the tree
static void preorder(Node root)
{
if (root == null )
return ;
System.out.print(root.data + " " );
preorder(root.left);
preorder(root.right);
}
// Function to convert the expression to a binary tree
static Node convertExpression(String str)
{
Stack<Node> s = new Stack<Node>();
// If the letter is the last letter of
// the string or is of the type :letter: or ?letter:
// we push the node pointer containing
// the letter to the stack
for ( int i = str.length() - 1 ; i >= 0 😉 {
if ((i == str.length() - 1 )
|| (i != 0 && ((str.charAt(i - 1 ) == ':'
&& str.charAt(i + 1 ) == ':' )
|| (str.charAt(i - 1 ) == '?'
&& str.charAt(i + 1 ) == ':' )))) {
s.push(createNewNode(str.charAt(i)));
}
// If we do not push the current
// letter node to stack,
// it means the top 2 nodes in
// the stack currently are the
// left and the right children of the current node
// So pop these elements and assign them as the
// children of the current letter node and then
// push this node into the stack
else {
Node lnode = (Node)s.peek();
s.pop();
Node rnode = (Node)s.peek();
s.pop();
Node node = createNewNode(str.charAt(i));
node.left = lnode;
node.right = rnode;
s.push(node);
}
i -= 2 ;
}
// Finally, there will be only 1 element
// in the stack which will be the
// root of the binary tree
return (Node)s.peek();
}
// Driver code
public static void main(String[] args)
{
String str = "a?b?c:d:e" ;
// Convert expression
Node root = convertExpression(str);
// Print the preorder traversal
preorder(root);
}
} // This code is contributed by divyesh072019. |
# Python3 implementation of the approach # Tree Structure class Node:
# Constructor to set the data of
# the newly created tree node
def __init__( self , data):
self .data = data
self .left = None
self .right = None
# Function to create a new node def createNewNode(data):
node = Node(data)
return node
# Function to print the preorder # traversal of the tree def preorder(root):
if (root = = None ):
return
print (root.data, end = " " )
preorder(root.left)
preorder(root.right)
# Function to convert the expression to a binary tree def convertExpression( Str ):
s = []
# If the letter is the last letter of
# the string or is of the type :letter: or ?letter:
# we push the node pointer containing
# the letter to the stack
i = len ( Str ) - 1
while i > = 0 :
if ((i = = len ( Str ) - 1 ) or (i ! = 0 and (( Str [i - 1 ] = = ':' and Str [i + 1 ] = = ':' )
or ( Str [i - 1 ] = = '?' and Str [i + 1 ] = = ':' )))):
s.append(createNewNode( Str [i]))
# If we do not push the current
# letter node to stack,
# it means the top 2 nodes in
# the stack currently are the
# left and the right children of the current node
# So pop these elements and assign them as the
# children of the current letter node and then
# push this node into the stack
else :
lnode = s[ - 1 ]
s.pop()
rnode = s[ - 1 ]
s.pop()
node = createNewNode( Str [i])
node.left = lnode
node.right = rnode
s.append(node)
i - = 2
# Finally, there will be only 1 element
# in the stack which will be the
# root of the binary tree
return s[ - 1 ]
Str = "a?b?c:d:e"
# Convert expression root = convertExpression( Str )
# Print the preorder traversal preorder(root) # This code is contributed by divyeshrabadiya07. |
// C# implementation of the approach using System;
using System.Collections;
class GFG {
// Class containing left and
// right child of current
// node and key value
class Node {
public char data;
public Node left, right;
public Node( char data)
{
this .data = data;
left = right = null ;
}
}
// Function to create a new node
static Node createNewNode( char data)
{
Node node = new Node(data);
return node;
}
// Function to print the preorder
// traversal of the tree
static void preorder(Node root)
{
if (root == null )
return ;
Console.Write(root.data + " " );
preorder(root.left);
preorder(root.right);
}
// Function to convert the expression to a binary tree
static Node convertExpression( string str)
{
Stack s = new Stack();
// If the letter is the last letter of
// the string or is of the type :letter: or ?letter:
// we push the node pointer containing
// the letter to the stack
for ( int i = str.Length - 1; i >= 0;) {
if ((i == str.Length - 1)
|| (i != 0 && ((str[i - 1] == ':'
&& str[i + 1] == ':' )
|| (str[i - 1] == '?'
&& str[i + 1] == ':' )))) {
s.Push(createNewNode(str[i]));
}
// If we do not push the current
// letter node to stack,
// it means the top 2 nodes in
// the stack currently are the
// left and the right children of the current node
// So pop these elements and assign them as the
// children of the current letter node and then
// push this node into the stack
else {
Node lnode = (Node)s.Peek();
s.Pop();
Node rnode = (Node)s.Peek();
s.Pop();
Node node = createNewNode(str[i]);
node.left = lnode;
node.right = rnode;
s.Push(node);
}
i -= 2;
}
// Finally, there will be only 1 element
// in the stack which will be the
// root of the binary tree
return (Node)s.Peek();
}
static void Main() {
string str = "a?b?c:d:e" ;
// Convert expression
Node root = convertExpression(str);
// Print the preorder traversal
preorder(root);
}
} // This code is contributed by decode2207. |
<script> // JavaScript implementation of the approach
class Node
{
constructor(data) {
this .left = null ;
this .right = null ;
this .data = data;
}
}
// Function to create a new node
function createNewNode(data)
{
let node = new Node(data);
return node;
}
// Function to print the preorder
// traversal of the tree
function preorder(root)
{
if (root == null )
return ;
document.write(root.data + " " );
preorder(root.left);
preorder(root.right);
}
// Function to convert the expression to a binary tree
function convertExpression(str)
{
let s = [];
// If the letter is the last letter of
// the string or is of the type :letter: or ?letter:
// we push the node pointer containing
// the letter to the stack
for (let i = str.length - 1; i >= 0;) {
if ((i == str.length - 1)
|| (i != 0 && ((str[i - 1] == ':'
&& str[i + 1] == ':' )
|| (str[i - 1] == '?'
&& str[i + 1] == ':' )))) {
s.push(createNewNode(str[i]));
}
// If we do not push the current
// letter node to stack,
// it means the top 2 nodes in
// the stack currently are the
// left and the right children of the current node
// So pop these elements and assign them as the
// children of the current letter node and then
// push this node into the stack
else {
let lnode = s[s.length - 1];
s.pop();
let rnode = s[s.length - 1];
s.pop();
let node = createNewNode(str[i]);
node.left = lnode;
node.right = rnode;
s.push(node);
}
i -= 2;
}
// Finally, there will be only 1 element
// in the stack which will be the
// root of the binary tree
return s[s.length - 1];
}
let str = "a?b?c:d:e" ;
// Convert expression
let root = convertExpression(str);
// Print the preorder traversal
preorder(root);
</script> |
a b c d e
Time Complexity: O(n)
Auxiliary Space: O(n) because using stack s