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:
CPP
// 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
// 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 |
C#
// 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 |
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
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.