Problem description

  • You are given an fully parenthesized arithmetic expression using only x, /, +, − operations.

  • Examples:

       ( 3 + 4 )
       ( 1 + ( 2 + 3 ) x ( 4 x 5 ) )
    

  • Problem:

    • Write an algorithm to evaluate expressions in this form

  • Edsger Dijkstra has developed a simple and elegant algorithm

  • The algorithm uses 2 stacks:

    1. An operand stack that stores the operands in the input

    2. An operator stack that stores the operators in the input

How does the Dijkstra 2 stack algorithm work ?

  • Consider the input ( 1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) ) :

                 ( 1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) )
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

     

How does the Dijkstra 2 stack algorithm work ?

  • Find the first occurence of a right parenthesis ):

                 ( 1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) )
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

     

How does the Dijkstra 2 stack algorithm work ?

  • Observe the last 2 operands and the last operation prior to the right parenthesis ):

                 ( 1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) )
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    This expression is guaranteed to be the most inner ( ) and can be evaluated first

How does the Dijkstra 2 stack algorithm work ?

  • We can therefore reduce the expression and replace it with its result:

                 ( 1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) )
    
                 ( 1 + (     5     x ( 4 x 5 ) ) )
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

     

How does the Dijkstra 2 stack algorithm work ?

  • Now find the next earliest occurence of the right parenthesis ):

                 ( 1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) )
    
                 ( 1 + (     5     x ( 4 x 5 ) ) )
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    This expression is guaranteed to be the most inner ( ) and can be evaluated first

How does the Dijkstra 2 stack algorithm work ?

  • Same reason: we can replace the 2 prior operands and its operator with the result:

                 ( 1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) )
    
                 ( 1 + (     5     x    20     ) )
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

     

How does the Dijkstra 2 stack algorithm work ?

  • Again: find the next earliest occurence of the right parenthesis ):

                 ( 1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) )
    
                 ( 1 + (     5     x    20     ) )
    
    
    
    
    
             Note: in order to evaluate  5 x 20
                   we need the results (5 and 20 )
                   pushed on the stack after
    	       they were evaluated !
    
    
    
    
    
    
    
    

    This expression is guaranteed to be the most inner ( ) and can be evaluated first

How does the Dijkstra 2 stack algorithm work ?

  • Same reason: we can replace the 2 prior operands and its operator with the result:

                 ( 1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) )
    
                 ( 1 + (     5     x    20     ) )
    
                 ( 1 +            100            )
    
    
                   
             Note: in order to evaluate  5 x 20
                   we need the results (5 and 20 )
                   pushed on the stack after
    	       they were evaluated !           
    	       
    
    
    
    
    
    
    

     

How does the Dijkstra 2 stack algorithm work ?

  • Again: find the next earliest occurence of the right parenthesis ):

                 ( 1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) )
    
                 ( 1 + (     5     x    20     ) )
    
                 ( 1 +            100            )
    
    
                   
          
      
      
    	         
    	       
    
    
    
    
    
    
    

    This expression is guaranteed to be the most inner ( ) and can be evaluated first

How does the Dijkstra 2 stack algorithm work ?

  • Same reason: we can replace the 2 prior operands and its operator with the result:

                 ( 1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) )
    
                 ( 1 + (     5     x    20     ) )
    
                 ( 1 +            100            )
    
                               101            
             
    
          
       Note: the result (101) would be
             pushed on the stack
    	 just like the other evaluations !
      
    	         
    	      
    
    
    
    

    When the input is exhausted, the algorithm will leave its output on the stack !

The design of the Dijkstra 2 stack algorithm

  • The algorithm must use the earliest 2 operands and the earliest operator before a right parenthesis ):

          .....  ( 2 + 3 ) ...
    

    This can be accomplished by:

    • storing the operands in the inputs in a operand stack

    • storing the operators in the inputs in a operator stack

  • The result of the computation (e.g.: 5) are operands for a later operation:

          ..... ( ( 2 + 3 ) x 20 ) ...
          ..... (     5     x 20 ) ...
    

    Therefore:

    • The result of an operation must be pushed on to operand stack

The design of the Dijkstra 2 stack algorithm

  • Notice that the left parenthsis ( does not convey any information.

  • Example:

    • Suppose you are given the following fully parenthesized arithmetic expression but without the left parenthesis:

                1 +     2 + 3 ) x   4 x 5 ) ) )
      

    • Working from the inside out, you can place these left parenthesis:

                1 +   ( 2 + 3 ) x ( 4 x 5 ) ) )
      Then:
                1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) )
      Finally:
              ( 1 + ( ( 2 + 3 ) x ( 4 x 5 ) ) )
      

Example of the execution of Dijkstra 2 stack algorithm

  • Suppose the fully bracketed expression is:

            ( ( 2 + 3 ) - 4 )
            ^
            |
         curr input
                                        Operands    Operators
                                        +------+     +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                            |      |     |      |  
                                        +------+	 +------+
    	                        --->|      |	 |      |<---
                                        +------+	 +------+
    
    
    

    Current input = (   ===>   Ignore

Example of the execution of Dijkstra 2 stack algorithm

  • Process the next input symbol:

            ( ( 2 + 3 ) - 4 )
              ^
              |
           curr input
                                        Operands    Operators
                                        +------+     +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                            |      |     |      |  
                                        +------+	 +------+
    	                        --->|      |	 |      |<---
                                        +------+	 +------+
    
    
    

    Current input = (   ===>   Ignore

Example of the execution of Dijkstra 2 stack algorithm

  • Process the next input symbol:

            ( ( 2 + 3 ) - 4 )
                ^
                |
             curr input
                                        Operands    Operators
                                        +------+     +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                        --->|      |     |      |  
                                        +------+	 +------+
    	                            |  2   |	 |      |<---
                                        +------+	 +------+
    
    
    

    Current input = 2   ===>   push(2) on the operand stack

Example of the execution of Dijkstra 2 stack algorithm

  • Process the next input symbol:

            ( ( 2 + 3 ) - 4 )
                  ^
                  |
               curr input
                                        Operands    Operators
                                        +------+     +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                        --->|      |     |      |<---
                                        +------+	 +------+
    	                            |  2   |	 |  +   |    
                                        +------+	 +------+
    
    
    

    Current input = +   ===>   push(+) on the operator stack

Example of the execution of Dijkstra 2 stack algorithm

  • Process the next input symbol:

            ( ( 2 + 3 ) - 4 )
                    ^
                    |
                 curr input
                                        Operands    Operators
                                        +------+     +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                        --->|      |	 |      |
                                        +------+	 +------+
    	                            |  3   |     |      |<---
                                        +------+	 +------+
    	                            |  2   |	 |  +   |    
                                        +------+	 +------+
    
    
    

    Current input = 3   ===>   push(3) on the operand stack

Example of the execution of Dijkstra 2 stack algorithm

  • Process the next input symbol:

            ( ( 2 + 3 ) - 4 )
                      ^
                      |
                   curr input
                                        Operands    Operators
                                        +------+     +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                        --->|      |	 |      |
                                        +------+	 +------+
    	                            |  3   |     |      |<---
                                        +------+	 +------+
    	                            |  2   |	 |  +   |    
                                        +------+	 +------+
       Compute:  3 + 2 
       Push result on the operand stack
    

    Current input = )   ===>   compute the expression

Example of the execution of Dijkstra 2 stack algorithm

  • Result:

            ( ( 2 + 3 ) - 4 )
                      ^
                      |
                   curr input
                                        Operands    Operators
                                        +------+     +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                        --->|      |     |      |    
                                        +------+	 +------+
    	                            |  5   |	 |      |<---
                                        +------+	 +------+
       Compute:  3 + 2 
       Push result on the operand stack
    

    Current input = )   ===>   compute the expression

Example of the execution of Dijkstra 2 stack algorithm

  • Process the next input symbol:

            ( ( 2 + 3 ) - 4 )
                        ^
                        |
                     curr input
                                        Operands    Operators
                                        +------+     +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                        --->|      |     |      |<---
                                        +------+	 +------+
    	                            |  5   |	 |  -   |    
                                        +------+	 +------+
      
      
    

    Current input = -   ===>   push(-) on the operator stack

Example of the execution of Dijkstra 2 stack algorithm

  • Process the next input symbol:

            ( ( 2 + 3 ) - 4 )
                          ^
                          |
                       curr input
                                        Operands    Operators
                                        +------+     +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                        --->|      |	 |      |
                                        +------+	 +------+
    	                            |  4   |     |      |<---
                                        +------+	 +------+
    	                            |  5   |	 |  -   |    
                                        +------+	 +------+
      
      
    

    Current input = 4   ===>   push(4) on the operand stack

Example of the execution of Dijkstra 2 stack algorithm

  • Process the next input symbol:

            ( ( 2 + 3 ) - 4 )
                            ^
                            |
                         curr input
                                        Operands    Operators
                                        +------+     +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                        --->|      |	 |      |
                                        +------+	 +------+
    	                            |  4   |     |      |<---
                                        +------+	 +------+
    	                            |  5   |	 |  -   |    
                                        +------+	 +------+
       Compute:  5 - 4 
       Push result on the operand stack  
    

    Current input = )   ===>   compute the expression

Example of the execution of Dijkstra 2 stack algorithm

  • Result:

            ( ( 2 + 3 ) - 4 )
                            ^
                            |
                         curr input
                                        Operands    Operators
                                        +------+     +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                        --->|      |     |      |    
                                        +------+	 +------+
    	                            |  1   |	 |      |<---
                                        +------+	 +------+
       Compute:  5 - 4 
       Push result on the operand stack  
    

    Current input = )   ===>   compute the expression

Example of the execution of Dijkstra 2 stack algorithm

  • Process the next input symbol: done

            ( ( 2 + 3 ) - 4 )
                              ^
                              |
                           curr input
                                        Operands    Operators
                                        +------+     +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                            |      |	 |      |
                                        +------+	 +------+
    	                        --->|      |     |      |    
                                        +------+	 +------+
    	                            |  1   |	 |      |<---
                                        +------+	 +------+
       
        
    

    The final result is stored in the operand stack

Pseudo code of the Dijkstra 2 stack algorithm

public static Integer eval(String[] inp)
{
    Stack<Integer> operandStk = new Stack<>();
    Stack<String>  operatorStk = new Stack<>();
    String s;

    for ( int i = 0; i < inp.length; i++ )
    {
        s = inp[i];   // s = next input symbol

	if ( s.equals("(") )
        {
            // "(" does not convey any information... 
        }
        else if ( s is an operator )  // Pseudo code
            operatorStk.push( s );
        else if ( s is a number )     // Pseudo code
            operandStk.push( Integer.parseInt(s) );  // Convert to integer
        else
	{   // ")" --> perform one operation
            int o2 = operandStk.pop();       // Get the last 2 operands
            int o1 = operandStk.pop();

            String op = operatorStk.pop();   // Get the last operator

            int r = operate(op, o1, o2);  // Perform the specified operation

            operandStk.push( r );            // Push the result on operand stack
	}
    }

    return operandStk.pop();  // Return result
}

Pseudo code of the Dijkstra 2 stack algorithm

The operate() method used to perform an arithmetic operation:

    public static int operate( String op, int o1, int o2 )
    {
        if ( op.equals("x") )  // Multiply
        {
            return( o1*o2 );
        }
        else if ( op.equals("/") )
        {
            return( o1/o2 );
        }
        else if ( op.equals("+") )
        {
            return( o1+o2 );
        }
        else if ( op.equals("-") )
        {
            return( o1-o2 );
        }
        else
            return 0;
    }

DEMO: demo/09-stack/dijkstra/Dijkstra.java + Demo.java + DemoX.java
java DemoX \( 1 + \( \( 2 + 3 \) x \( 4 x 5 \) \) \)