1

I'm reading Sedgewick's book on algorithms in C and I'm looking for an algorithm to evaluate postfix expressions (addition and multiplication only) without using a stack. I tried to implement one but I always get nowhere.

I have a simple C implementation for prefix evaluation

int eval()
{
  int x = 0;

  while (a[i] == ' ')
    i++;
  if (a[i] == '+')
    {
      i++;
      return eval() + eval();
    }
  if (a[i] == '*')
    {
      i++;
      return eval() * eval();
    }
  while ( (a[i] >= '0') && (a[i] <= '9'))
    x = 10*x + (a[i++]-'0');
  return x;
 }

and I was wondering if it's possible to do something as elegant as this but for postfix evaluation.

caisah
  • 113

7 Answers7

6

I wouldn't exactly call using a global variable as a string index counter 'elegant', but in a nutshell: No, you can't, because you have no idea how to combine the various numbers you find until you get to the operators. Until you do, you have to store them somewhere - and to get the right result, whatever your storage strategy is will ultimately boil down to stack semantics.

Kilian Foth
  • 110,899
1

you pass the top 2 in the stack as parameter at each point, this way when you get to an operator you go up the stack when you see a value you go down the stack and when you get back you try again:

here is the magic:

eval(int x1, int x2)
{
 do{
   int x = 0;
   while (a[i] == ' ')
     i++;
   if (a[i] == '+')
    {
      i++;
      return x2+x1;// go up the stack with the resulting value
    }
   if (a[i] == '*')
    {
      i++;
      return x1*x2;
    }
   while ( (a[i] >= '0') && (a[i] <= '9'))
      x = 10*x + (a[i++]-'0');
   x2 = eval(x2, xt); // replace the old top with the result and try again
 }while(true);
}

you just need to add 2 functions to handle the errors when operators appear as the first 2 terms:

eval()
{
 int x = 0;
  while (a[i] == ' ')
    i++;
 if (a[i] == '+')
    {
      i++;
      return ERROR;
    }
  if (a[i] == '*')
    {
      i++;
      return ERROR;
    }
  while ( (a[i] >= '0') && (a[i] <= '9'))
    x = 10*x + (a[i++]-'0');
  return eval(x);
}

eval(int x1)
{
 int x = 0;
  while (a[i] == ' ')
    i++;
 if (a[i] == '+')
    {
      i++;
      return ERROR;
    }
  if (a[i] == '*')
    {
      i++;
      return ERROR;
    }
  while ( (a[i] >= '0') && (a[i] <= '9'))
    x = 10*x + (a[i++]-'0');
  return eval(x1, x);
}
ratchet freak
  • 25,986
1

and I was wondering if it's possible to do something as elegant as this but for postfix evaluation.

Postfix notation isn't meant to be processed with a call stack or recursion or really anything of that nature. Its designed for nice, tight implementations that just have a simple loop and a stack next to it. These fall into the realm of stack machines and are often found in embedded systems because of their simplicity. You find things like forth, postscript and the jvm as very successful stack machines (see Wikipedia - Category stack based virtual machines) along with venerable HP rpn calculator.

The elegance of postfix can be seen in the simple loop:

while not end of file
    read into var
    if var is not operand
        push var
    else if var is '+'
        pop into v1
        pop into v2
        push v1 + v2
    else if var is '*'
        pop into v1
        pop info v2
        push v1 * v2

And thus you go through and implement all the operands and you're done. dc has 27 operands (things like print (pop and print) P, print (just print) p, print the stack f, clear the stack c, etc...). You can read them at dc.1 man page. I will admit there are some more elegant structures for implementing the operands rather than a huge if else if cascade depending on the language... but you get the idea.

The elegance of the system is its simplicity. You don't have to worry about stack frames, calling conventions, and the like when implementing it. You've got a stack and a variable or two.

0

I would consider the problem as:

  • a parsing problem. read some good compiler text book like the Dragon book. So parse your expression into some Abstract Syntax Tree sitting in the virtual address space of your process.

  • then, evaluate that AST (in some environment).

The above approach fits for any expression-like language (not only postfix, but also prefix, or infix, etc...).

Alternatively, a postfix expression can be considered as some bytecode for a stack automaton (or pushdown automaton) based interpreter.

0

The referred book by Sedgewick already covers evaluating postfix expressions using a stack, and it explains why that ADT is naturally suitable to do so. This exercise is in the context of recursion, which is more suitable for evaluating prefix expressions. The code block in OP's is taken verbatim from there.

My solution that doesn't involve stacks reads the string right-to-left. The only changes to the provided program are in the increment operators and in the handling of the operands. Of course, the whole expression has to be already stored in a:

char *a;
int i = strlen(a) - 1;

int eval(void) { int x = 0; while (a[i] == ' ') i--; if (a[i] == '+') { i--; return eval() + eval(); } if (a[i] == '') { i--; return eval() eval(); } int j = 1; while ((a[i] >= '0') && (a[i] <= '9')) { x += j * (a[i--] - '0'); j *= 10; } return x; }

Piolie
  • 1
0

Trying to use recursion for this problem is totally inappropriate. You are trying to use the wrong tool, like using a paint brush to cut down a tree. That’s why it doesn’t work.

gnasher729
  • 49,096
-1

Definition: postfix = identifier | <postfix> <postfix> <operator>

To evaluate a postfix expression, we scan it from the last character to the first one in the expression, then perform the operation indicated by the last character on the two operands on the left, evaluated recursively.

char *a;
int i = strlen(a)-1;
int eval()
{
  int x = 0;
  int factor = 1;
  while (a[i] == ' ') i--;
  if (a[i] == '+')
  { i--;  return eval() + eval(); }
  if (a[i] == '*')
  { i--; return eval() * eval(); }
  while ('0' <= a[i] && a[i] <= '9')
  { x = x + (a[i--] - '0') * factor;  factor *= 10; }
  return x;
}
RaidenF
  • 1,579
zzz
  • 1