Given a string representing infix notation. The task is to convert it to an expression tree.
Expression Tree is a binary tree where the operands are represented by leaf nodes and operators are represented by intermediate nodes. No node can have a single child.
Construction of Expression tree
The algorithm follows a combination of shunting yard along with postfix-to-expression tree conversion.
Consider the below line:
((s[i]!='^' && p[stC.top()]>=p[s[i]]) || (s[i]=='^' && p[stC.top()]>p[s[i]])))
You might remember that unlike ‘+’, ‘-‘, ‘*’ and ‘/’; ‘^’ is right associative.
In simpler terms, a^b^c is a^(b^c) not (a^b)^c. So it must be evaluated from the right.
Now lets take a look at how does the algorithm work,(Take a quick glance at the code to get a better idea of the variables used)
Let us have an expression s = ((a+b)*c-e*f) currently both the stacks are empty- (we'll use C to denote the char stack and N for node stack) s[0] = '(' ((a+b)*c-e*f) ^ C|(|, N| | s[1] = '(' ((a+b)*c-e*f) ^ |(| C|(|, N| | s[2] = 'a' ((a+b)*c-e*f) ^ |(| C|(|, N|a| s[3] = '+' ((a+b)*c-e*f) ^ |+| |(| C|(|, N|a| s[4] = 'b' ((a+b)*c-e*f) ^ |+| |(| |b| C|(|, N|a| s[5] = ')' ((a+b)*c-e*f) ^ |+| t = '+' + |(| |b| -> t1= 'b' / \ -> C|(|, N|a| t2= 'a' a b C|(|, N|+| s[6] = '*' ((a+b)*c-e*f) ^ |*| C|(|, N|+| s[7] = 'c' ((a+b)*c-e*f) ^ |*| |c| C|(|, N|+| s[8] = '-' ((a+b)*c-e*f) now (C.top(*)>s[8](-)) ^ t = '*' * |*| |c| t1 = c / \ -> |-| C|(|, N|+| t2 = + + c C|(|, N|*| / \ a b s[9] = 'e' ((a+b)*c-e*f) ^ |-| |e| C|(|, N|*| s[10] = '*' ((a+b)*c-e*f) now (C.top(-)>s[10](*)) ^ |*| |-| |e| C|(|, N|*| s[11] = 'f' ((a+b)*c-e*f) ^ |*| |f| |-| |e| C|(|, N|*| s[12] = ')' ((a+b)*c-e*f) 1> ^ |*| |f| t = '*' * |-| |e| -> t1= 'f' -> / \ -> |-| |*| C|(|, N|*| t2= 'e' e f C|(|, N|*| 2> t = '-' - |-| |*| -> t1= '*' -> / \ -> C|(|, N|*| t2= '*' * * C| |, N|-| / \ / \ + c e f / \ a b now make (-) 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;
// Tree Structure typedef struct node
{ char data;
struct node *left, *right;
} * nptr; // Function to create new node nptr newNode( char c)
{ nptr n = new node;
n->data = c;
n->left = n->right = nullptr;
return n;
} // Function to build Expression Tree nptr build(string& s) { // Stack to hold nodes
stack<nptr> stN;
// Stack to hold chars
stack< char > stC;
nptr t, t1, t2;
// Prioritising the operators
int p[123] = { 0 };
p[ '+' ] = p[ '-' ] = 1, p[ '/' ] = p[ '*' ] = 2, p[ '^' ] = 3,
p[ ')' ] = 0;
for ( int i = 0; i < s.length(); i++)
{
if (s[i] == '(' ) {
// Push '(' in char stack
stC.push(s[i]);
}
// Push the operands in node stack
else if ( isalpha (s[i]))
{
t = newNode(s[i]);
stN.push(t);
}
else if (p[s[i]] > 0)
{
// If an operator with lower or
// same associativity appears
while (
!stC.empty() && stC.top() != '('
&& ((s[i] != '^' && p[stC.top()] >= p[s[i]])
|| (s[i] == '^'
&& p[stC.top()] > p[s[i]])))
{
// Get and remove the top element
// from the character stack
t = newNode(stC.top());
stC.pop();
// Get and remove the top element
// from the node stack
t1 = stN.top();
stN.pop();
// Get and remove the currently top
// element from the node stack
t2 = stN.top();
stN.pop();
// Update the tree
t->left = t2;
t->right = t1;
// Push the node to the node stack
stN.push(t);
}
// Push s[i] to char stack
stC.push(s[i]);
}
else if (s[i] == ')' ) {
while (!stC.empty() && stC.top() != '(' )
{
t = newNode(stC.top());
stC.pop();
t1 = stN.top();
stN.pop();
t2 = stN.top();
stN.pop();
t->left = t2;
t->right = t1;
stN.push(t);
}
stC.pop();
}
}
t = stN.top();
return t;
} // Function to print the post order // traversal of the tree void postorder(nptr root)
{ if (root)
{
postorder(root->left);
postorder(root->right);
cout << root->data;
}
} // Driver code int main()
{ string s = "(a^b^(c/d/e-f)^(x*y-m*n))" ;
s = "(" + s;
s += ")" ;
nptr root = build(s);
// Function call
postorder(root);
return 0;
} |
// Java implementation of the approach import java.util.*;
class GFG
{ // Tree Structure static class nptr
{ char data;
nptr left, right;
} ; // Function to create new node static nptr newNode( char c)
{ nptr n = new nptr();
n.data = c;
n.left = n.right = null ;
return n;
} // Function to build Expression Tree static nptr build(String s)
{ // Stack to hold nodes
Stack<nptr> stN = new Stack<>();
// Stack to hold chars
Stack<Character> stC = new Stack<>();
nptr t, t1, t2;
// Prioritising the operators
int []p = new int [ 123 ];
p[ '+' ] = p[ '-' ] = 1 ;
p[ '/' ] = p[ '*' ] = 2 ;
p[ '^' ] = 3 ;
p[ ')' ] = 0 ;
for ( int i = 0 ; i < s.length(); i++)
{
if (s.charAt(i) == '(' ) {
// Push '(' in char stack
stC.add(s.charAt(i));
}
// Push the operands in node stack
else if (Character.isAlphabetic(s.charAt(i)))
{
t = newNode(s.charAt(i));
stN.add(t);
}
else if (p[s.charAt(i)] > 0 )
{
// If an operator with lower or
// same associativity appears
while (
!stC.isEmpty() && stC.peek() != '('
&& ((s.charAt(i) != '^' && p[stC.peek()] >= p[s.charAt(i)])
|| (s.charAt(i) == '^'
&& p[stC.peek()] > p[s.charAt(i)])))
{
// Get and remove the top element
// from the character stack
t = newNode(stC.peek());
stC.pop();
// Get and remove the top element
// from the node stack
t1 = stN.peek();
stN.pop();
// Get and remove the currently top
// element from the node stack
t2 = stN.peek();
stN.pop();
// Update the tree
t.left = t2;
t.right = t1;
// Push the node to the node stack
stN.add(t);
}
// Push s[i] to char stack
stC.push(s.charAt(i));
}
else if (s.charAt(i) == ')' ) {
while (!stC.isEmpty() && stC.peek() != '(' )
{
t = newNode(stC.peek());
stC.pop();
t1 = stN.peek();
stN.pop();
t2 = stN.peek();
stN.pop();
t.left = t2;
t.right = t1;
stN.add(t);
}
stC.pop();
}
}
t = stN.peek();
return t;
} // Function to print the post order // traversal of the tree static void postorder(nptr root)
{ if (root != null )
{
postorder(root.left);
postorder(root.right);
System.out.print(root.data);
}
} // Driver code public static void main(String[] args)
{ String s = "(a^b^(c/d/e-f)^(x*y-m*n))" ;
s = "(" + s;
s += ")" ;
nptr root = build(s);
// Function call
postorder(root);
} } // This code is contributed by aashish1995 |
# Python3 implementation of the approach # Tree Structure class nptr:
# Constructor to set the data of
# the newly created tree node
def __init__( self , c):
self .data = c
self .left = None
self .right = None
# Function to create new node def newNode(c):
n = nptr(c)
return n
# Function to build Expression Tree def build(s):
# Stack to hold nodes
stN = []
# Stack to hold chars
stC = []
# Prioritising the operators
p = [ 0 ] * ( 123 )
p[ ord ( '+' )] = p[ ord ( '-' )] = 1
p[ ord ( '/' )] = p[ ord ( '*' )] = 2
p[ ord ( '^' )] = 3
p[ ord ( ')' )] = 0
for i in range ( len (s)):
if (s[i] = = '(' ):
# Push '(' in char stack
stC.append(s[i])
# Push the operands in node stack
elif (s[i].isalpha()):
t = newNode(s[i])
stN.append(t)
elif (p[ ord (s[i])] > 0 ):
# If an operator with lower or
# same associativity appears
while ( len (stC) ! = 0 and stC[ - 1 ] ! = '(' and ((s[i] ! = '^' and p[ ord (stC[ - 1 ])] > = p[ ord (s[i])])
or (s[i] = = '^' and
p[ ord (stC[ - 1 ])] > p[ ord (s[i])]))):
# Get and remove the top element
# from the character stack
t = newNode(stC[ - 1 ])
stC.pop()
# Get and remove the top element
# from the node stack
t1 = stN[ - 1 ]
stN.pop()
# Get and remove the currently top
# element from the node stack
t2 = stN[ - 1 ]
stN.pop()
# Update the tree
t.left = t2
t.right = t1
# Push the node to the node stack
stN.append(t)
# Push s[i] to char stack
stC.append(s[i])
elif (s[i] = = ')' ):
while ( len (stC) ! = 0 and stC[ - 1 ] ! = '(' ):
t = newNode(stC[ - 1 ])
stC.pop()
t1 = stN[ - 1 ]
stN.pop()
t2 = stN[ - 1 ]
stN.pop()
t.left = t2
t.right = t1
stN.append(t)
stC.pop()
t = stN[ - 1 ]
return t
# Function to print the post order # traversal of the tree def postorder(root):
if (root ! = None ):
postorder(root.left)
postorder(root.right)
print (root.data, end = "")
s = "(a^b^(c/d/e-f)^(x*y-m*n))"
s = "(" + s
s + = ")"
root = build(s)
# Function call postorder(root) # This code is contributed by divyeshrabadiya07. |
// C# implementation of the approach using System;
using System.Collections.Generic;
class GFG
{ // Tree Structure public class nptr
{ public char data;
public nptr left, right;
} ; // Function to create new node static nptr newNode( char c)
{ nptr n = new nptr();
n.data = c;
n.left = n.right = null ;
return n;
} // Function to build Expression Tree static nptr build(String s)
{ // Stack to hold nodes
Stack<nptr> stN = new Stack<nptr>();
// Stack to hold chars
Stack< char > stC = new Stack< char >();
nptr t, t1, t2;
// Prioritising the operators
int []p = new int [123];
p[ '+' ] = p[ '-' ] = 1;
p[ '/' ] = p[ '*' ] = 2;
p[ '^' ] = 3;
p[ ')' ] = 0;
for ( int i = 0; i < s.Length; i++)
{
if (s[i] == '(' )
{
// Push '(' in char stack
stC.Push(s[i]);
}
// Push the operands in node stack
else if ( char .IsLetter(s[i]))
{
t = newNode(s[i]);
stN.Push(t);
}
else if (p[s[i]] > 0)
{
// If an operator with lower or
// same associativity appears
while (stC.Count != 0 && stC.Peek() != '('
&& ((s[i] != '^' && p[stC.Peek()] >= p[s[i]])
|| (s[i] == '^' && p[stC.Peek()] > p[s[i]])))
{
// Get and remove the top element
// from the character stack
t = newNode(stC.Peek());
stC.Pop();
// Get and remove the top element
// from the node stack
t1 = stN.Peek();
stN.Pop();
// Get and remove the currently top
// element from the node stack
t2 = stN.Peek();
stN.Pop();
// Update the tree
t.left = t2;
t.right = t1;
// Push the node to the node stack
stN.Push(t);
}
// Push s[i] to char stack
stC.Push(s[i]);
}
else if (s[i] == ')' )
{
while (stC.Count != 0 && stC.Peek() != '(' )
{
t = newNode(stC.Peek());
stC.Pop();
t1 = stN.Peek();
stN.Pop();
t2 = stN.Peek();
stN.Pop();
t.left = t2;
t.right = t1;
stN.Push(t);
}
stC.Pop();
}
}
t = stN.Peek();
return t;
} // Function to print the post order // traversal of the tree static void postorder(nptr root)
{ if (root != null )
{
postorder(root.left);
postorder(root.right);
Console.Write(root.data);
}
} // Driver code public static void Main(String[] args)
{ String s = "(a^b^(c/d/e-f)^(x*y-m*n))" ;
s = "(" + s;
s += ")" ;
nptr root = build(s);
// Function call
postorder(root);
} } // This code is contributed by aashish1995 |
<script> // JavaScript implementation of the approach
// Tree Structure
class nptr
{
constructor(c) {
this .left = null ;
this .right = null ;
this .data = c;
}
}
// Function to create new node
function newNode(c)
{
let n = new nptr(c);
return n;
}
// Function to build Expression Tree
function build(s)
{
// Stack to hold nodes
let stN = [];
// Stack to hold chars
let stC = [];
let t, t1, t2;
// Prioritising the operators
let p = new Array(123);
p[ '+' .charCodeAt()] = p[ '-' .charCodeAt()] = 1;
p[ '/' .charCodeAt()] = p[ '*' .charCodeAt()] = 2;
p[ '^' .charCodeAt()] = 3;
p[ ')' .charCodeAt()] = 0;
for (let i = 0; i < s.length; i++)
{
if (s[i] == '(' )
{
// Push '(' in char stack
stC.push(s[i]);
}
// Push the operands in node stack
else if ((/[a-zA-Z]/).test(s[i]))
{
t = newNode(s[i]);
stN.push(t);
}
else if (p[s[i].charCodeAt()] > 0)
{
// If an operator with lower or
// same associativity appears
while (stC.length != 0 && stC[stC.length - 1] != '('
&& ((s[i] != '^' &&
p[stC[stC.length - 1].charCodeAt()] >=
p[s[i].charCodeAt()])
|| (s[i] == '^' &&
p[stC[stC.length - 1].charCodeAt()] >
p[s[i].charCodeAt()])))
{
// Get and remove the top element
// from the character stack
t = newNode(stC[stC.length - 1]);
stC.pop();
// Get and remove the top element
// from the node stack
t1 = stN[stN.length - 1];
stN.pop();
// Get and remove the currently top
// element from the node stack
t2 = stN[stN.length - 1];
stN.pop();
// Update the tree
t.left = t2;
t.right = t1;
// Push the node to the node stack
stN.push(t);
}
// Push s[i] to char stack
stC.push(s[i]);
}
else if (s[i] == ')' )
{
while (stC.length != 0 &&
stC[stC.length - 1] != '(' )
{
t = newNode(stC[stC.length - 1]);
stC.pop();
t1 = stN[stN.length - 1];
stN.pop();
t2 = stN[stN.length - 1];
stN.pop();
t.left = t2;
t.right = t1;
stN.push(t);
}
stC.pop();
}
}
t = stN[stN.length - 1];
return t;
}
// Function to print the post order
// traversal of the tree
function postorder(root)
{
if (root != null )
{
postorder(root.left);
postorder(root.right);
document.write(root.data);
}
}
let s = "(a^b^(c/d/e-f)^(x*y-m*n))" ;
s = "(" + s;
s += ")" ;
let root = build(s);
// Function call
postorder(root);
</script> |
abcd/e/f-xy*mn*-^^^
The time Complexity is O(n) as each character is accessed only once.
The space Complexity is O(n) as (char_stack + node_stack) <= n