Convert Infix to Postfix Using a Stack

The stack is the whole trick. It holds operators that cannot be written down yet because something stronger might still be coming. Press play below and watch it fill and drain, one token at a time.

Try:

Why a stack, and not something else

When you read A + B * C left to right and reach the +, you cannot write it down yet. You do not know whether the thing after B will be weaker than + (in which case + goes out now) or stronger (in which case it has to wait). So the + has to be held.

And when several operators are held at once, the one you always release first is the most recent one — because it is the innermost, most tightly bound. Last in, first out. That is precisely a stack, which is why converting infix to postfix using a stack is not merely one approach among many; it is the natural fit for the problem.

The one-line summary

Operands are never in doubt, so they go straight out. Operators are always in doubt, so they wait on the stack until something proves it is their turn.

Anatomy of the operator stack: push, pop and peek all act on the topTHE OPERATOR STACKpush()pop()/(+BOTTOM OF STACKtoppeek() reads hereOnly this endis reachable —last in, first out.
Every operation touches the same end. push adds to the top, pop removes from the top, and peek reads the top without removing it — which is what lets the algorithm compare precedence before deciding.

The six stack rules

Every token you read falls into one of six cases. Apply the matching rule and move on — there is nothing else to decide.

  1. Operand (a letter or number) Append it to the output immediately. It never touches the stack.
  2. Opening bracket ( Push it. It acts as a floor marker: popping will stop when it is reached.
  3. Closing bracket ) Pop operators to the output until ( is on top, then pop that ( and throw both brackets away.
  4. Operator, stack empty or ( on top Push it. There is nothing above it that could outrank it.
  5. Operator, weaker than or equal to the top Pop the top to the output and check again. Keep popping while the condition holds, then push the new operator. The equal case is what makes A - B - C come out as A B - C -; the exception is ^, which is right associative and does not pop its equals.
  6. End of the expression Pop everything still on the stack to the output. If a ( turns up here, the expression had unbalanced brackets.
Decision flow: which stack rule applies to each kind of tokenFOR EVERY TOKEN YOU READtokenoperandappend it straight to the output(push it as a marker)pop to output until ( , then discard bothoperatorpop while the top outranks it, then push
The whole algorithm in one picture: four kinds of token, four responses. Nothing else has to be decided.

Worked example, stack shown at every step

Converting A + B * C - (D / E). The stack is written left to right with the top on the right, which is the convention the visualiser above uses too.

Infix to postfix conversion using a stack: A + B * C - (D / E)
# Token Stack action Stack Output
1AOperand → outputemptyA
2+Stack empty → push+A
3BOperand → output+A B
4*Higher than + → push+ *A B
5COperand → output+ *A B C
6-Pop *, pop +, then push --A B C * +
7(Push as marker- (A B C * +
8DOperand → output- (A B C * + D
9/Top is ( → push- ( /A B C * + D
10EOperand → output- ( /A B C * + D E
11)Pop /, discard the (-A B C * + D E /
12endPop -emptyA B C * + D E / -

Notice step 6. The - is weaker than * and equal to +, so both come off before it goes on. Students who only pop the strictly stronger operator get A B C * D E / - + here, which is a different expression entirely.

Nested brackets

Nesting needs no extra rules. Each ( adds another marker and each ) unwinds down to the nearest one, so the stack simply grows deeper. Converting ((A + B) * (C - D)) ^ E:

((A + B) * (C - D)) ^ E

  (            stack: ( (
  A + B        →  A B +   flushed when the first ) arrives
  *            stack: ( *
  (C - D)      →  C D -   flushed when the second ) arrives
  )            pops *     output: A B + C D - *
  ^ E          stack: ^   output: A B + C D - * E

  postfix:  A B + C D - * E ^

Load that expression into the visualiser with the nested button above to watch the stack reach three deep and come back down.

Stack operations you need

The algorithm uses four operations, all of them O(1). Any stack implementation works — an array with an integer top, a linked list, or your language's built-in type.

Stack operations used in infix to postfix conversion
Operation What it does Used for
push(x)Add x to the topStoring an operator or (
pop()Remove and return the topSending a waiting operator to the output
peek()Read the top without removing itComparing precedence before deciding
isEmpty()Is the stack empty?Guarding every peek and pop

peek() is the one people forget. You have to look at the top before you commit to popping it, otherwise you cannot compare precedence without destroying the value.

How large does the stack get?

In the worst case the stack holds n entries for an n-token expression — that happens with input like ((((a)))) or a long right-associative chain such as a ^ b ^ c ^ d, where nothing can be released until the very end. Sizing a fixed array stack at the length of the input string is therefore always safe, and it is what the C implementation does.

Five mistakes that cost marks

  1. Popping only strictly greater precedence. Equal precedence must also pop, for every left-associative operator. Otherwise A - B - C comes out wrong.
  2. Treating ^ like the others. Exponentiation is right associative, so it is the single exception: it does not pop an equal ^.
  3. Writing brackets into the output. Postfix has no brackets. A ( is discarded when its ) arrives; neither is ever emitted.
  4. Popping past a ( on a closing bracket. The ( is a floor. Stop there, or you will drag operators out of an enclosing sub-expression too early.
  5. Forgetting the final flush. When the input ends, the stack is usually not empty. Everything left on it belongs at the end of the output, popped top-down.

Frequently asked questions

Why is a stack used to convert infix to postfix?

Because an operator read from an infix expression cannot be output immediately — a higher-precedence operator may still follow it. It must be held, and when several are held the most recently pushed one is always released first, since it is the most tightly bound. That last-in-first-out behaviour is exactly what a stack provides.

What is pushed onto the stack during conversion?

Only operators and opening brackets. Operands go straight to the output and never enter the stack. Closing brackets are never pushed either — they trigger popping and are then discarded along with their matching opening bracket.

When do you pop from the stack?

In three situations: when a closing bracket arrives (pop until the matching opening bracket), when an incoming operator has lower or equal precedence than the top (pop while that holds), and when the input is finished (pop everything that remains).

How big should the stack be?

The length of the input expression is always enough. In the worst case — deeply nested brackets, or a chain of right-associative operators — every token could be on the stack at once, but never more than that.

What if the stack still has a "(" on it at the end?

The expression had an unbalanced opening bracket and is invalid. A correct implementation reports an error at that point rather than emitting the bracket into the output.

Can you convert infix to postfix without a stack?

You can — by building an expression tree and reading it in post-order, or by recursive descent parsing. Both are more work and both use a stack implicitly (the call stack, or the tree's structure). For a single left-to-right pass, the explicit stack is the simplest correct method.