Search code examples
functionclassbinary-treeinfix-notation

use a binary tree to encode infix arithmetic expressions on integers


This is a question from aws educate. I have been thinking about this for a long time and I am not really getting anywhere.

You want to use a binary tree to encode infix arithmetic expressions on integers. Operations are addition and multiplication Draw a picture of what the tree looks like. Write a class definition. Write an evaluate() member function. How would you make your evaluate() iterative instead of recursive

If I could get an explanation that would be fine or some example too


Solution

  • Illustration - binary tree to encode infix arithmetic expressions on integers

    Binary Tree

    As you can see, the leafs are the value (or literal) and the other nodes contain arithmetic operators (+, - , /, *)

    Some Code - recusion

    In Java, you could use the recursion to solve this problem (under the condition that the tree's height is not to big)

    public class Main {
    
        public static void main(String[] args) {
            // op1=(1 + 2)
            Node op1 = new Node(1, "+", 2);
            System.out.println("op1="+op1.evaluate()); // op1=3
    
            // op2=(1 + 2) + 3
            Node op2 = new Node(op1, "+", 3);
            System.out.println("op2="+op2.evaluate()); // op2=6
    
            // op3=(4 * 5)
            Node op3 = new Node(4, "*", 5);
            System.out.println("op3="+op3.evaluate()); // op3=20
    
            // op4=((1+2)+3)*(4*5)
            Node op4 = new Node(op2, "*", op3);
            System.out.println("op4="+op4.evaluate()); // op4=120
        }
    }
    
    class Node {
    
        private Node left;
        private Node right;
        private String operatorOrLiteral;
    
        public Node(String value){
            this.operatorOrLiteral = value;
        }
    
        public Node(Node left, String operation, Node right){
            this.operatorOrLiteral = operation;
            this.left = left;
            this.right = right;
        }
    
        public Node(int literal1, String operation, int literal2){
            this(new Node(Integer.toString(literal1)), operation, new Node(Integer.toString(literal2)));
        }
    
        public Node(Node left, String operation, int literal2) {
            this(left, operation, new Node(Integer.toString(literal2)));
        }
    
        public Node(int literal1, String operation, Node right) {
            this(new Node(Integer.toString(literal1)), operation, right);
        }
    
        public int evaluate(){
            if(isLiteral()) {
                return Integer.parseInt(operatorOrLiteral);
            }
    
            switch (operatorOrLiteral) {
                case "*": return left.evaluate() * right.evaluate();
                case "/": return left.evaluate() / right.evaluate();
                case "-": return left.evaluate() - right.evaluate();
                case "+": return left.evaluate() + right.evaluate();
                default: throw new IllegalArgumentException(operatorOrLiteral + " is not recognised");
            }
        }
    
        private boolean isLiteral() {
            return left == null && right == null;
        }
    
        public String toString() {
            if(isLiteral()) {
                return operatorOrLiteral;
            }
    
            return "(" + left.toString() + operatorOrLiteral + right.toString() + ")";
        }
    }
    

    Some Code - iterative

    Or as @David Sanders as mentioned, you can work with tree traversal.