Application of Stack : Infix to Postfix Conversion

 

Objectives of this lecture

q       Review Postfix (and Infix) Notation

q       Learn how Stack may be used to convert from infix expression to postfix

 

Review of Postfix (and Infix notation)

q       We recall that a problem with infix notation is the ambiguity involved in evaluating expressions in that notation.

      E.g   2+3*4 (is it equal to 20 or 14?)

q       The table of precedence rule must then be applied to resolve the problem.

q       Another way of representing expressions is to use prefix (operator before operands) or postfix (operator after operands).

q       In either of these approaches, the precedence rule is embedded in the expression itself, making it more efficient to evaluate the expression.

q       Because of this efficiency, most compilers convert infix expressions to postfix before generating the code.

q       The following table shows sample expressions in all three format:

Prefix

Infix

Postfix

* 3 4

3 * 4

3 4 *

+ 3 * 4 5

3 + 4 * 5

3 4 5 * +

* + 3 4 5

(3 + 4) * 5

3 4 + 5 *

 

q       We also recall that Stack can be used to easily evaluate a post fix expression as shown by the following function:

 

/* Evaluates postfix expression of digit operands

 Pre:  postfix is a string containing valid postfix string

 Post: the value of the postfix string has been  returned

 Uses: Stack functions

*/

int Eval(char *postfix)

{

  StackEntry op1, op2, result;

  Stack stack;

  int i=0;

  int len=strlen(postfix);  // must put string.h in common.h

 

  CreateStack(&stack);


  for (i=0; i<len; i++)

  { if (postfix[i] != ' ')

      if (postfix[i] >= '0' && postfix[i] <= '9')

          Push(postfix[i] - '0', &stack);

      else

      {  Pop(&op2, &stack);

           Pop(&op1, &stack);

           switch (postfix[i])

          {  case '+' : Push(op1+op2, &stack); break;

              case '-' : Push(op1-op2, &stack); break;

              case '*' : Push(op1*op2, &stack); break;

              case '/' : Push(op1/op2, &stack); break;

             default : Error("nError in input");

         }

      }

  }

  Pop(&result, &stack);

  return result;

}

 

q       The above example assumes the presence of a postfix expression.  Next, we shall again make use of Stack to convert from infix to postfix expression.

 

Infix to Postfix Conversion (non  - parenthesized)

q       We first consider a simple infix expression that does not involve parenthesis   :e.g. a + b*c + e/f

q       Observe that the operands appear in the same order regardless of the notation.  Thus, we can achieve this using the following algorithm.

Ø      when we reach an operand, we simply add it to the postfix string.

Ø      When we reach an operator, we perform the following:

Ø      If the stack is empty, we push the operator in the stack,

Ø      Else, we must pop all operators that have higher or equal  precedence than the current operator and append then to the postfix string, then we push the current operator on the stack

Ø      When the infix string is exhausted,  we pop all operators on the stack and append then to the postfix string.

 

Example 1: infix = a + b * c

character

postfix

stack

a

a

empty

+

a

+

b

ab

+

*

ab

+*

c

abc

+*

 

Pop the remaining operators and append to postfix string à abc*+

 

Example 2: infix = a * b + c

character

postfix

stack

a

a

empty

*

a

*

b

ab

*

+

ab*

+

c

ab*c

+

 

 Pop the remaining operators and append to postfix string à ab*c+

 

q       The following function implements the above algorithm.

 

/* Converts non-parenthesized infix string to postfix

Pre: the infix contains a valid infix string

Post: the resulting postfix is returned

Uses: ctostr, an_operator, Higher, StackTop and Stack operations

*/

char *Convert (char *infix)

{ char *postfix, ch;

   StackEntry op;

   Stack stack;

   int i;

   int len=strlen(infix); 

 

   CreateStack(&stack); // initialize stack to empty

   postfix[0] = '\0';   // initialize postfix to empty

 

  for (i=0; i<len; i++)

  { ch=infix[i];  

     if (ch != ' ')  //skip spaces

       if (!an_operator(ch))

     strcat(postfix, ctostr(ch));

      else

      {  while ( (!StackEmpty(&stack)) && Higher(StackTop(&stack), ch))

      {  Pop(&op, &stack);

         strcat(postfix, ctostr(op));

      }

      Push(ch, &stack);

      }

   }

 

   while (! StackEmpty(&stack))

   {  Pop(&op, &stack);

      strcat(postfix, ctostr(op));

   }

 

  return postfix;

}

q       The Higher functions can be implemented as follows:

//returns true if op1 is of higher or equal precedence than op2

Boolean Higher(char op1, char op2)

{  int prec1, prec2;  //precedence level of op1 and op2

 

   if (op1=='+' || op1=='-')

      prec1=2;

   else

      prec1=3;

 

   if (op2=='+' || op2=='-')

      prec2=2;

   else

      prec2=3;

   return (prec1 >= prec2);

}   

q       The following functions are left as an exercise:

//returns true if a given character is an operator (+, -, *, /)

Boolean an_operator(char ch);

 

// converts a character to string

char *ctostr(char ch);

 

//returns the top item of the stack without deleting it from the stack

StackEntry StackTop(Stack *s);  //add this to the stack ADT.

 

General Case of Parenthesized Expressions

q       We observe that when a parenthesis is encountered, we need to suspend all operations until its content are processed.  Thus, we can generalize the algorithm by treating the parenthesis as operators and making the following changes to the Higher function:

1.      When a left parenthesis is encountered on the infix, we need to give it the highest precedence so that it can be push on the stack.

Higher(anyop, ‘(‘) à false

2.      To correctly process the content of the parenthesis, we need to be able to stack operators on it.  Thus, we need to treat a left parenthesis already in the stack with the lowest precedence value:

Higher(‘(‘,anyop) àfalse

3.      When we encounter the right parenthesis from the infix string, we need to give it the lowest precedence than any operator except the left parenthesis so that the content of the parenthesis can be popped and appended to the postfix string.

Higher (All but left, ‘)’ ) à true

4.      After popping the the content of the parenthesis, we must pop the left parenthesis and discard it.

 

q       We can get all these settings by using the following precedence rules:

operator

precedence

‘(‘ as op1

0

‘)’ as op2

1

+, -  (always)

2

*, /  (always)

3

‘(‘ as op2

4

 

q       Assuming the an_operator and Higher functions are modified as described above, then the following is the modified version of the conversion function.

 

/* Converts a general parenthesized infix string to postfix

Pre: the infix contains a valid infix string

Post: the resulting postfix is returned

Uses: ctostr, an_operator, Higher, StackTop and Stack operations

*/

char *Convert (char *infix)

{char *postfix, ch;

  StackEntry op;

  Stack stack;

  int i;

  int len=strlen(infix); 

 

  CreateStack(&stack); // initialize stack to empty

  postfix[0] = '\0';   // initialize postfix to empty

  for (i=0; i<len; i++)

  { ch=infix[i];  

    if (ch != ' ')  //skip spaces

      if (!an_operator(ch))

      strcat(postfix, ctostr(ch));

      else

      {  while ( (!StackEmpty(&stack)) && Higher(StackTop(&stack), ch))

          {  Pop(&op, &stack);

              strcat(postfix, ctostr(op));

          }

          if (ch == ‘)’)

                pop(&op, &stack);  //pop the corresponding left parenthesis

          else

       Push(ch, &stack);

      }

   }

   while (! StackEmpty(&stack))

   {  Pop(&op, &stack);

      strcat(postfix, ctostr(op));

   }

  return postfix;

}

 

Exercise: : Modify the functions an_operator and Higher as described above and write a main program to test these function. (Note: Need to compile these using the project tool).