Close Menu
    Code and Debug
    • Home
    • Our Courses
    • Blog
    • About Us
    • Contact Us
    Facebook X (Twitter) Instagram YouTube WhatsApp
    • Home
    • Our Courses
    • Blog
    • About Us
    • Contact Us
    Facebook Instagram YouTube LinkedIn WhatsApp
    Code and Debug – BlogCode and Debug – Blog
    Code and Debug – BlogCode and Debug – Blog
    Home»Data Structures & Algorithms»Infix, Postfix, Prefix Conversions explained in Python
    Data Structures & Algorithms

    Infix, Postfix, Prefix Conversions explained in Python

    codeanddebugBy codeanddebug6 August 2025No Comments35 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Reddit Telegram Email
    Share
    Facebook Twitter LinkedIn Pinterest Email

    Postfix, prefix, and infix are three common notations used to write arithmetic expressions. In infix notation, the operator is placed between operands (e.g., A + B), and is the most familiar to humans. Prefix notation (Polish notation) places the operator before the operands (e.g., + A B), while postfix notation (Reverse Polish notation) places the operator after the operands (e.g., A B +). Prefix and postfix notations are widely used in computer science as they allow efficient expression evaluation without parentheses.

    Contents:
     [show]
    • Infix to Postfix Conversion Explanation
      • Approach/Intuition
      • Code
      • Code Explanation
      • Dry Run Example
      • Edge Cases to Consider
      • Time and Space Complexity
        • Time Complexity: O(n)
        • Space Complexity: O(n)
      • Applications
    • Infix to Prefix Conversion Explanation
      • Approach/Intuition
      • Code
      • Code Explanation
      • Dry Run Example
      • Edge Cases to Consider
      • Time and Space Complexity
        • Time Complexity: O(n)
        • Space Complexity: O(n)
      • Applications
    • Postfix to Infix Conversion Explanation
      • Approach/Intuition
      • Code
      • Code Explanation
      • Dry Run Example
      • Edge Cases to Consider
      • Time and Space Complexity
        • Time Complexity: O(n)
        • Space Complexity: O(n)
      • Applications
    • Prefix to Infix Conversion Explanation
      • Approach/Intuition
      • Code
      • Code Explanation
      • Dry Run Example
      • Edge Cases to Consider
      • Time and Space Complexity
        • Time Complexity: O(n)
        • Space Complexity: O(n)
      • Applications
    • Postfix to Prefix Conversion Explanation
      • Approach/Intuition
      • Code
      • Code Explanation
      • Dry Run Example
      • Edge Cases to Consider
      • Time and Space Complexity
        • Time Complexity: O(n)
        • Space Complexity: O(n)
      • Applications
    • Prefix to Postfix Conversion Explanation
      • Approach/Intuition
      • Code
      • Code Explanation
      • Dry Run Example
      • Edge Cases to Consider
      • Time and Space Complexity
        • Time Complexity: O(n)
        • Space Complexity: O(n)
      • Applications

    Infix to Postfix Conversion Explanation

    Approach/Intuition

    Infix, postfix, and prefix are different ways of writing mathematical expressions. Infix notation is what we commonly use in everyday mathematics (e.g., “3 + 4”), where operators are placed between operands. Postfix notation (also known as Reverse Polish Notation) places operators after their operands (e.g., “3 4 +”).

    The key advantage of postfix notation is that it eliminates the need for parentheses and operator precedence rules. This makes postfix expressions much easier for computers to evaluate using a simple stack-based algorithm.

    The conversion from infix to postfix relies on understanding operator precedence and using a stack to properly reorder the elements. The core intuition involves:

    1. Operands (numbers, variables) go directly to the output.
    2. Opening parentheses go onto the stack.
    3. Closing parentheses trigger popping operators from the stack until the matching opening parenthesis.
    4. When encountering an operator, pop operators with higher or equal precedence from the stack to the output.
    5. Finally, pop any remaining operators from the stack to the output.

    This approach ensures that operators are sequenced in the correct order of evaluation in the postfix expression.

    Code

    class Solution:
        def precedence(self, ch):
            # Define operator precedence hierarchy
            if ch == "+" or ch == "-":
                return 1
            if ch == "*" or ch == "/":
                return 2
            if ch == "^":
                return 3
            return 0  # For non-operators like '(' and ')'
    
        def InfixtoPostfix(self, s):
            stack = []    # Stack to help with operator ordering
            result = []   # To store the postfix expression
    
            for char in s:
                # If character is an operand, add it directly to result
                if ("a" <= char <= "z") or ("A" <= char <= "Z") or ("0" <= char <= "9"):
                    result.append(char)
               
                # If character is '(', push it to the stack
                elif char == "(":
                    stack.append(char)
               
                # If character is ')', pop until '(' is encountered
                elif char == ")":
                    while stack and stack[-1] != "(":
                        result.append(stack.pop())
                    stack.pop()  # Discard the '('
               
                # If character is an operator
                else:
                    # Pop operators with higher or equal precedence
                    while stack and self.precedence(stack[-1]) >= self.precedence(char):
                        result.append(stack.pop())
                    stack.append(char)  # Push current operator
    
            # Pop remaining operators from the stack
            while stack:
                result.append(stack.pop())
    
            return "".join(result)  # Convert list to string

    Code Explanation

    The implementation consists of two main functions:

    1. precedence(ch): This helper function assigns a numeric value to each operator representing its precedence:
      • Higher numbers indicate higher precedence
      • Addition and subtraction have precedence 1
      • Multiplication and division have precedence 2
      • Exponentiation has precedence 3
      • Other characters (including parentheses) have precedence 0
    2. InfixtoPostfix(s): This is the main conversion function:
      • It uses a stack for temporary storage of operators and parentheses
      • It processes each character in the input string one by one:
        • For operands (letters and digits): Directly append to the result list
        • For opening parenthesis ‘(‘: Push onto the stack to mark its position
        • For closing parenthesis ‘)’: Pop operators from the stack and append to result until the matching opening parenthesis is found. Then discard the opening parenthesis without adding it to the result.
        • For operators (+, -, *, /, ^):
          • While there are operators on stack with higher or equal precedence, pop them and append to result
          • Then push the current operator onto the stack
      • After processing all characters, any remaining operators on the stack are popped and appended to the result
      • Finally, join the result list into a string and return it

    The algorithm ensures that operators appear in the postfix expression in the correct order of evaluation, respecting operator precedence and parentheses.

    Dry Run Example

    Let’s trace through the conversion of the infix expression “a+b*(c^d-e)^(f+g*h)-i” to postfix:

    1. Initialize: stack = [], result = []
    2. Process ‘a’: Append to result → result = [‘a’]
    3. Process ‘+’: Stack is empty, push to stack → stack = [‘+’], result = [‘a’]
    4. Process ‘b’: Append to result → result = [‘a’, ‘b’]
    5. Process ‘*’: Has higher precedence than ‘+’, push to stack → stack = [‘+’, ‘*’], result = [‘a’, ‘b’]
    6. Process ‘(‘: Push to stack → stack = [‘+’, ‘*’, ‘(‘], result = [‘a’, ‘b’]
    7. Process ‘c’: Append to result → result = [‘a’, ‘b’, ‘c’]
    8. Process ‘^’: Push to stack → stack = [‘+’, ‘*’, ‘(‘, ‘^’], result = [‘a’, ‘b’, ‘c’]
    9. Process ‘d’: Append to result → result = [‘a’, ‘b’, ‘c’, ‘d’]
    10. Process ‘-‘: Lower precedence than ‘^’, pop ‘^’ → stack = [‘+’, ‘*’, ‘(‘, ‘-‘], result = [‘a’, ‘b’, ‘c’, ‘d’, ‘^’]
    11. Process ‘e’: Append to result → result = [‘a’, ‘b’, ‘c’, ‘d’, ‘^’, ‘e’]
    12. Process ‘)’: Pop operators until ‘(‘ → stack = [‘+’, ‘*’], result = [‘a’, ‘b’, ‘c’, ‘d’, ‘^’, ‘e’, ‘-‘]
    13. Process ‘^’: Higher precedence than ‘*’, push to stack → stack = [‘+’, ‘*’, ‘^’], result = [‘a’, ‘b’, ‘c’, ‘d’, ‘^’, ‘e’, ‘-‘]
    14. Process ‘(‘: Push to stack → stack = [‘+’, ‘*’, ‘^’, ‘(‘], result = [‘a’, ‘b’, ‘c’, ‘d’, ‘^’, ‘e’, ‘-‘]
    15. Continue with remaining characters…

    Final result after processing all characters: “abcd^e-fgh+^+i-“

    Edge Cases to Consider

    1. Empty Input: The algorithm would return an empty string, which is correct.
    2. Single Operand: For input like “a”, the output would just be “a”, which is correct.
    3. Only Operators: Not a valid infix expression, but the algorithm would attempt to process it.
    4. Unbalanced Parentheses: If the input has unbalanced parentheses, the algorithm may give incorrect results or fail.
    5. Invalid Characters: The algorithm assumes valid input with operands and supported operators.
    6. Multiple Digit Numbers: The current implementation treats each digit as a separate operand. For multi-digit numbers, additional logic would be needed to group consecutive digits.
    7. Negative Numbers: The algorithm doesn’t handle unary operators (like a negative sign at the beginning of a number). This would require additional logic.

    Time and Space Complexity

    Time Complexity: O(n)

    • We iterate through the input string once, and each character is processed in constant time.
    • Each character is pushed onto the stack at most once and popped at most once.
    • Therefore, the time complexity is linear in the length of the input string.

    Space Complexity: O(n)

    • In the worst case (e.g., an expression with many opening parentheses), the stack might need to store a significant portion of the input.
    • The result list will eventually contain all operands and operators from the input.
    • Therefore, the space complexity is also linear in the length of the input string.

    Applications

    Infix to postfix conversion has several practical applications:

    1. Compiler Design: Postfix notation is used in compilers for expression evaluation.
    2. Calculator Implementation: Many calculators convert infix expressions to postfix for evaluation.
    3. Expression Evaluation Engines: Databases and spreadsheet applications often use postfix for formula evaluation.
    4. Programming Languages: Some languages like Forth and PostScript use postfix notation natively.

    Infix to Prefix Conversion Explanation

    Approach/Intuition

    Prefix notation (also known as Polish notation) is a way to write mathematical expressions where operators precede their operands. For example, the infix expression “a + b” becomes “+ a b” in prefix notation. This format, like postfix notation, eliminates the need for parentheses and simplifies expression evaluation for computers.

    The key insight for converting infix to prefix is that we can leverage our knowledge of infix to postfix conversion with some clever modifications:

    1. Reverse the infix expression
    2. Swap opening and closing parentheses (since we reversed the string)
    3. Apply a modified infix to postfix algorithm
    4. Reverse the result to get the prefix expression

    This approach works because reversing an infix expression and swapping parentheses essentially transforms the problem into a “right-to-left” version of the infix to postfix conversion. After we obtain the “reverse postfix” expression, reversing it again gives us the correct prefix notation.

    The clever part of this algorithm is recognizing that we don’t need to design a completely new conversion algorithm – we can adapt the infix to postfix algorithm with minimal changes.

    Code

    class Solution:
        def precedence(self, ch):
            # Define operator precedence hierarchy
            if ch == "+" or ch == "-":
                return 1
            if ch == "*" or ch == "/":
                return 2
            if ch == "^":
                return 3
            return 0  # For non-operators like '(' and ')'
    
        def infixToPrefix(self, s):
            # Step 1: Reverse the infix expression
            s = s[::-1]
    
            # Step 2: Swap opening and closing parentheses
            s = s.replace("(", "temp").replace(")", "(").replace("temp", ")")
    
            stack = []
            result = []
    
            # Step 3: Modified infix to postfix algorithm
            for char in s:
                # If character is an operand, add it directly to result
                if ("a" <= char <= "z") or ("A" <= char <= "Z") or ("0" <= char <= "9"):
                    result.append(char)
               
                # If character is '(', push it to the stack
                elif char == "(":
                    stack.append(char)
               
                # If character is ')', pop until '(' is encountered
                elif char == ")":
                    while stack and stack[-1] != "(":
                        result.append(stack.pop())
                    stack.pop()  # Discard the '('
               
                # If character is an operator
                else:
                    # Note the change to '>' from '>=' in the infix to postfix algorithm
                    # This handles right-associativity properly
                    while stack and self.precedence(stack[-1]) > self.precedence(char):
                        result.append(stack.pop())
                    stack.append(char)  # Push current operator
    
            # Pop remaining operators from the stack
            while stack:
                result.append(stack.pop())
    
            # Step 4: Reverse the result to get prefix expression
            return "".join(result[::-1])

    Code Explanation

    The implementation consists of the same precedence function from the infix to postfix conversion, plus the main infixToPrefix function:

    1. precedence(ch): This helper function assigns a numeric value to each operator representing its precedence:
      • Addition and subtraction have precedence 1
      • Multiplication and division have precedence 2
      • Exponentiation has precedence 3
      • Other characters have precedence 0
    2. infixToPrefix(s): The main conversion function with four key steps:
      • Step 1: Reverse the input string using slice notation s[::-1].
      • Step 2: Swap opening and closing parentheses, since they need to be flipped after reversal. This is done using sequential replacements with a temporary placeholder to avoid conflicts.
      • Step 3: Apply a modified infix to postfix algorithm:
        • Process each character in the (reversed) input
        • Operands go directly to the result list
        • Opening parentheses go onto the stack
        • Closing parentheses trigger popping operators until the matching opening parenthesis
        • For operators, pop operators with strictly higher precedence (note the > instead of >= used in postfix conversion – this subtle change handles operator associativity correctly in the prefix notation)
      • Step 4: Reverse the result using result[::-1] to get the final prefix expression

    The subtle but important difference in the operator precedence comparison (> instead of >=) ensures that the order of operations is preserved correctly for prefix notation, especially for operators with the same precedence level.

    Dry Run Example

    Let’s trace through the conversion of the infix expression “a+b*c” to prefix:

    1. Reverse the infix: “c*b+a”
    2. Swap parentheses: No parentheses in this example, so the string remains “c*b+a”
    3. Apply modified infix to postfix:
      • Initialize: stack = [], result = []
      • Process ‘c’: Append to result → result = [‘c’]
      • Process ‘*’: Stack is empty, push to stack → stack = [‘*’], result = [‘c’]
      • Process ‘b’: Append to result → result = [‘c’, ‘b’]
      • Process ‘+’: Lower precedence than ‘‘, pop ‘‘ → stack = [‘+’], result = [‘c’, ‘b’, ‘*’]
      • Process ‘a’: Append to result → result = [‘c’, ‘b’, ‘*’, ‘a’]
      • No more characters. Pop remaining operators: → result = [‘c’, ‘b’, ‘*’, ‘a’, ‘+’]
    4. Reverse the result: “+” + “a” + “” + “b” + “c” = “+abc”

    The final prefix expression is “+abc”, which correctly represents “a+bc” in prefix notation.

    Let’s try a more complex example with parentheses: “a+(b*c)”

    1. Reverse the infix: “)c*b(+a”
    2. Swap parentheses: “(c*b)+a”
    3. Apply modified infix to postfix:
      • Initialize: stack = [], result = []
      • Process ‘(‘: Push to stack → stack = [‘(‘], result = []
      • Process ‘c’: Append to result → result = [‘c’]
      • Process ‘*’: Push to stack → stack = [‘(‘, ‘*’], result = [‘c’]
      • Process ‘b’: Append to result → result = [‘c’, ‘b’]
      • Process ‘)’: Pop until ‘(‘ → stack = [], result = [‘c’, ‘b’, ‘*’]
      • Process ‘+’: Push to stack → stack = [‘+’], result = [‘c’, ‘b’, ‘*’]
      • Process ‘a’: Append to result → result = [‘c’, ‘b’, ‘*’, ‘a’]
      • Pop remaining operators: → result = [‘c’, ‘b’, ‘*’, ‘a’, ‘+’]
    4. Reverse the result: “+a*bc”, which is the correct prefix form.

    Edge Cases to Consider

    1. Empty Input: The algorithm would return an empty string, which is correct.
    2. Single Operand: For input like “a”, the output would just be “a”, which is correct.
    3. Only Operators: Not a valid infix expression, but the algorithm would attempt to process it.
    4. Unbalanced Parentheses: If the input has unbalanced parentheses, the algorithm may give incorrect results or fail.
    5. Right-Associative Operators: The algorithm handles right-associative operators like exponentiation (^) correctly due to the > comparison in the precedence check.
    6. Multiple Digit Numbers: The current implementation treats each digit as a separate operand. For multi-digit numbers, additional logic would be needed.
    7. Negative Numbers: The algorithm doesn’t handle unary operators (like a negative sign). This would require additional preprocessing.

    Time and Space Complexity

    Time Complexity: O(n)

    • We process each character in the input string once.
    • String reversal takes O(n) time.
    • Parenthesis swapping takes O(n) time.
    • The infix to postfix conversion part takes O(n) time, with each character pushed and popped at most once.
    • Final result reversal takes O(n) time.
    • Overall, the time complexity is linear in the length of the input string.

    Space Complexity: O(n)

    • The reversed input string requires O(n) space.
    • The stack might store up to O(n) characters in the worst case.
    • The result list will eventually store O(n) characters.
    • Therefore, the space complexity is linear in the length of the input string.

    Applications

    Prefix notation has several practical applications:

    1. Compiler Design: Some programming language compilers use prefix notation as an intermediate representation.
    2. Functional Programming: Languages like LISP use prefix notation for function calls and expressions.
    3. Expression Evaluation: Prefix notation can be evaluated using a simple algorithm with a stack.
    4. Logical Expressions: Prefix notation is sometimes used in logical expressions and Boolean algebra.

    Postfix to Infix Conversion Explanation

    Approach/Intuition

    Converting from postfix notation back to infix notation is an interesting problem that showcases the power of stack-based parsing. While infix notation is the standard mathematical notation we’re all familiar with (e.g., “a + b”), postfix notation (also known as Reverse Polish Notation) places operators after their operands (e.g., “ab+”).

    The key insight for this conversion is that postfix expressions are designed to be evaluated using a stack. When converting to infix, we can use a similar stack-based approach, but instead of computing values, we build infix expression strings.

    The algorithm works as follows:

    1. Scan the postfix expression from left to right
    2. When an operand is encountered, push it onto the stack
    3. When an operator is encountered, pop the top two elements from the stack (these are the operands)
    4. Combine these operands with the operator, surrounded by parentheses, to form a partial infix expression
    5. Push this new expression back onto the stack
    6. After processing the entire postfix expression, the stack will contain a single element – the complete infix expression

    The parentheses around each operation ensure that the resulting infix expression preserves the correct order of operations that was encoded in the postfix expression.

    Code

    class Solution:
        def postToInfix(self, s):
            # Stack to store operands or partial infix expressions
            stack = []
    
            for char in s:
                # If character is an operand (letter or digit), push it to the stack
                if char.isalnum():
                    stack.append(char)
                else:
                    # If character is an operator, pop two operands
                    operand2 = stack.pop()  # Second operand (popped first)
                    operand1 = stack.pop()  # First operand (popped second)
    
                    # Combine operands with the operator, surrounded by parentheses
                    new_expr = f"({operand1}{char}{operand2})"
    
                    # Push the resulting expression back onto the stack
                    stack.append(new_expr)
    
            # The final element in the stack is the complete infix expression
            return stack[-1]

    Code Explanation

    The implementation uses a single stack and processes each character in the postfix expression one at a time:

    1. Stack Initialization: We create an empty list to serve as our stack for storing operands and intermediate expressions.
    2. Character Processing:
      • For each character in the postfix expression:
        • If it’s an alphanumeric character (operand), we push it directly onto the stack
        • If it’s an operator, we:
          • Pop the top element from the stack (second operand in infix notation)
          • Pop the next element from the stack (first operand in infix notation)
          • Combine them with the operator in the form “(operand1 operator operand2)”
          • Push this new expression back onto the stack
    3. Final Result: After processing all characters, the stack will contain exactly one element – the complete infix expression.

    The key aspects of this implementation are:

    • Using isalnum() to identify operands (both letters and numbers)
    • The order of popping operands matters: the second operand is popped first, and the first operand is popped second
    • Adding parentheses around each operation to preserve precedence
    • Using f-strings for clean string concatenation

    Dry Run Example

    Let’s trace through the conversion of the postfix expression “ab+cd-*” to infix:

    1. Initialize: stack = []
    2. Process ‘a’: Push to stack → stack = [‘a’]
    3. Process ‘b’: Push to stack → stack = [‘a’, ‘b’]
    4. Process ‘+’:
      • Pop two operands: operand2 = ‘b’, operand1 = ‘a’
      • Create new expression: “(a+b)”
      • Push to stack → stack = [‘(a+b)’]
    5. Process ‘c’: Push to stack → stack = [‘(a+b)’, ‘c’]
    6. Process ‘d’: Push to stack → stack = [‘(a+b)’, ‘c’, ‘d’]
    7. Process ‘-‘:
      • Pop two operands: operand2 = ‘d’, operand1 = ‘c’
      • Create new expression: “(c-d)”
      • Push to stack → stack = [‘(a+b)’, ‘(c-d)’]
    8. Process ‘*’:
      • Pop two operands: operand2 = ‘(c-d)’, operand1 = ‘(a+b)’
      • Create new expression: “((a+b)*(c-d))”
      • Push to stack → stack = [‘((a+b)*(c-d))’]
    9. Final result: “((a+b)*(c-d))”

    This infix expression correctly represents the computation encoded in the original postfix expression “ab+cd-“, which means “(a+b)(c-d)”.

    Edge Cases to Consider

    1. Empty Input: The algorithm would attempt to access an empty stack, causing an error. Input validation should be added.
    2. Single Operand: For input like “a”, the output would just be “a”, which is correct.
    3. Invalid Postfix Expression: If the input isn’t a valid postfix expression (e.g., not enough operands for operators), the algorithm will fail when attempting to pop from the stack.
    4. Complex Expressions: The algorithm handles arbitrarily complex expressions correctly, as long as they are valid postfix expressions.
    5. Operator Associativity: The parentheses ensure that the original operation order is preserved, regardless of operator associativity.
    6. Multi-Character Operands: The current implementation assumes single-character operands. For multi-character operands, additional tokenization would be needed.

    Time and Space Complexity

    Time Complexity: O(n)

    • We iterate through the input string once, processing each character exactly once.
    • Each character is either pushed onto the stack once, or causes two pops and one push.
    • String concatenation operations are generally O(1) for small strings.
    • Overall, the time complexity is linear in the length of the input string.

    Space Complexity: O(n)

    • In the worst case, the stack might contain nearly all characters from the input.
    • Additionally, as we build infix expressions with parentheses, the final expression can be larger than the input.
    • Therefore, the space complexity is O(n), where n is the length of the input string.

    Applications

    Understanding postfix to infix conversion has several practical applications:

    1. Compiler Design: Compilers often convert between different notations during the parsing and code generation stages.
    2. Calculator Implementation: Many calculators that use postfix internally might need to display results in infix.
    3. Expression Evaluation: Systems that evaluate expressions in postfix form may need to show intermediate steps in infix notation for debugging or user display.
    4. Programming Language Tools: Debuggers and code analyzers might convert between notations to present information to developers.

    Prefix to Infix Conversion Explanation

    Approach/Intuition

    Prefix notation (also known as Polish notation) places operators before their operands. For example, the infix expression “a + b” is written as “+ a b” in prefix notation. Converting from prefix to infix requires a different approach than postfix to infix, but still leverages the power of stack-based parsing.

    The key insight for this conversion is that we need to process the prefix expression in reverse order (right to left). This is because in prefix notation, operators precede their operands, so when working right to left, we encounter the operands before their corresponding operators.

    The algorithm works as follows:

    1. Scan the prefix expression from right to left
    2. When an operand is encountered, push it onto the stack
    3. When an operator is encountered, pop the top two elements from the stack (these are the operands)
    4. Combine these operands with the operator, surrounded by parentheses, to form a partial infix expression
    5. Push this new expression back onto the stack
    6. After processing the entire prefix expression, the stack will contain a single element – the complete infix expression

    The crucial difference from postfix conversion is the direction of traversal and the order of operands when forming expressions.

    Code

    class Solution:
        def preToInfix(self, s):
            # Stack to store operands or partial infix expressions
            stack = []
    
            # Process the prefix expression from right to left
            for char in s[::-1]:
                # If character is an operand (letter or digit), push it to the stack
                if char.isalnum():
                    stack.append(char)
                else:
                    # If character is an operator, pop two operands
                    operand1 = stack.pop()  # First operand
                    operand2 = stack.pop()  # Second operand
    
                    # Combine operands with the operator, surrounded by parentheses
                    new_expr = f"({operand1}{char}{operand2})"
    
                    # Push the resulting expression back onto the stack
                    stack.append(new_expr)
    
            # The final element in the stack is the complete infix expression
            return stack[-1]

    Code Explanation

    The implementation uses a single stack and processes each character in the prefix expression from right to left:

    1. Stack Initialization: We create an empty list to serve as our stack for storing operands and intermediate expressions.
    2. Character Processing:
      • We use slice notation s[::-1] to iterate through the string in reverse order
      • For each character:
        • If it’s an alphanumeric character (operand), we push it directly onto the stack
        • If it’s an operator, we:
          • Pop the top element from the stack (first operand in infix notation)
          • Pop the next element from the stack (second operand in infix notation)
          • Combine them with the operator in the form “(operand1 operator operand2)”
          • Push this new expression back onto the stack
    3. Final Result: After processing all characters, the stack will contain exactly one element – the complete infix expression.

    Note the order of popping operands: unlike in postfix conversion, the first operand popped corresponds to the first operand in the resulting infix expression. This is because when processing the prefix expression from right to left, we encounter operands in the reverse order than we would in a postfix expression processed from left to right.

    Dry Run Example

    Let’s trace through the conversion of the prefix expression “*+ab-cd” to infix:

    1. Initialize: stack = []
    2. Process (from right to left):
      • ‘d’: Push to stack → stack = [‘d’]
      • ‘c’: Push to stack → stack = [‘d’, ‘c’]
      • ‘-‘:
        • Pop two operands: operand1 = ‘c’, operand2 = ‘d’
        • Create new expression: “(c-d)”
        • Push to stack → stack = [‘(c-d)’]
      • ‘b’: Push to stack → stack = [‘(c-d)’, ‘b’]
      • ‘a’: Push to stack → stack = [‘(c-d)’, ‘b’, ‘a’]
      • ‘+’:
        • Pop two operands: operand1 = ‘a’, operand2 = ‘b’
        • Create new expression: “(a+b)”
        • Push to stack → stack = [‘(c-d)’, ‘(a+b)’]
      • ‘*’:
        • Pop two operands: operand1 = ‘(a+b)’, operand2 = ‘(c-d)’
        • Create new expression: “((a+b)*(c-d))”
        • Push to stack → stack = [‘((a+b)*(c-d))’]
    3. Final result: “((a+b)*(c-d))”

    This infix expression correctly represents the computation encoded in the original prefix expression “+ab-cd”, which means “(a+b)(c-d)”.

    Edge Cases to Consider

    1. Empty Input: The algorithm would return an error for an empty input string. Input validation should be added.
    2. Single Operand: For input like “a”, the output would just be “a”, which is correct.
    3. Invalid Prefix Expression: If the input isn’t a valid prefix expression (e.g., not enough operands for operators), the algorithm will fail when attempting to pop from the stack.
    4. Complex Expressions: The algorithm handles arbitrarily complex expressions correctly, as long as they are valid prefix expressions.
    5. Operator Associativity: The parentheses ensure that the original operation order is preserved, regardless of operator associativity.
    6. Multi-Character Operands: The current implementation assumes single-character operands. For multi-character operands, additional tokenization would be needed.

    Time and Space Complexity

    Time Complexity: O(n)

    • We iterate through the input string once, processing each character exactly once.
    • String reversal takes O(n) time.
    • Each character is either pushed onto the stack once, or causes two pops and one push.
    • String concatenation operations are generally O(1) for small strings.
    • Overall, the time complexity is linear in the length of the input string.

    Space Complexity: O(n)

    • In the worst case, the stack might contain nearly all characters from the input.
    • Additionally, as we build infix expressions with parentheses, the final expression can be larger than the input.
    • Therefore, the space complexity is O(n), where n is the length of the input string.

    Applications

    Understanding prefix to infix conversion has several practical applications:

    1. Programming Language Processing: Some languages like LISP use prefix notation, and tools might need to convert between notations.
    2. Expression Evaluators: Systems that need to display prefix expressions in a more human-readable format.
    3. Compiler Design: Compilers that work with different expression notations during various processing stages.
    4. Mathematical Software: Tools that allow users to input expressions in different notations.

    Postfix to Prefix Conversion Explanation

    Approach/Intuition

    Converting between different notations of mathematical expressions is a fundamental operation in compiler design and expression parsing. In this case, we’re converting from postfix notation (Reverse Polish Notation) to prefix notation (Polish Notation).

    Postfix notation places operators after their operands (e.g., “ab+”), while prefix notation places operators before their operands (e.g., “+ab”). Both notations eliminate the need for parentheses, unlike infix notation.

    The key insight for this conversion is that we can leverage the stack-based nature of postfix evaluation, but instead of computing values, we build prefix expression strings. When we encounter an operator in the postfix expression, we pop two operands from the stack, combine them with the operator in prefix form, and push the result back.

    The algorithm follows these steps:

    1. Scan the postfix expression from left to right
    2. When an operand is encountered, push it onto the stack
    3. When an operator is encountered, pop the top two elements from the stack
    4. Create a new expression with the operator first, followed by the first operand, then the second operand
    5. Push this new expression back onto the stack
    6. After processing the entire postfix expression, the stack will contain a single element – the complete prefix expression

    Code

    class Solution:
        def postToPre(self, s):
            # Stack to store operands or partial prefix expressions
            stack = []
    
            # Process each character in postfix expression
            for char in s:
                # If the character is an operand, push it to the stack
                if char.isalnum():
                    stack.append(char)
                else:
                    # Pop two operands from the stack
                    operand2 = stack.pop()  # Second operand (popped first)
                    operand1 = stack.pop()  # First operand (popped second)
    
                    # Combine the operands with the operator in prefix form
                    new_expr = f"{char}{operand1}{operand2}"
    
                    # Push the result back onto the stack
                    stack.append(new_expr)
    
            # The final element in the stack is the prefix expression
            return stack[-1]

    Code Explanation

    The implementation uses a single stack to process the postfix expression character by character:

    1. Stack Initialization: We create an empty list to serve as our stack for storing operands and intermediate expressions.
    2. Character Processing:
      • For each character in the postfix expression:
        • If it’s an alphanumeric character (an operand), we push it directly onto the stack
        • If it’s an operator, we:
          • Pop the top element from the stack (second operand)
          • Pop the next element from the stack (first operand)
          • Combine them with the operator in prefix form: “operator operand1 operand2”
          • Push this new expression back onto the stack
    3. Final Result: After processing all characters, the stack will contain exactly one element – the complete prefix expression.

    The key aspects of this implementation are:

    • Using isalnum() to identify operands (both letters and numbers)
    • The order of popping operands matters: the second operand is popped first, and the first operand is popped second
    • The new expression is formed with the operator first, followed by operand1 and operand2
    • Unlike in the conversion to infix, we don’t need parentheses since prefix notation doesn’t require them

    Dry Run Example

    Let’s trace through the conversion of the postfix expression “ab+cd-*” to prefix:

    1. Initialize: stack = []
    2. Process ‘a’: Push to stack → stack = [‘a’]
    3. Process ‘b’: Push to stack → stack = [‘a’, ‘b’]
    4. Process ‘+’:
      • Pop two operands: operand2 = ‘b’, operand1 = ‘a’
      • Create new expression: “+ab”
      • Push to stack → stack = [‘+ab’]
    5. Process ‘c’: Push to stack → stack = [‘+ab’, ‘c’]
    6. Process ‘d’: Push to stack → stack = [‘+ab’, ‘c’, ‘d’]
    7. Process ‘-‘:
      • Pop two operands: operand2 = ‘d’, operand1 = ‘c’
      • Create new expression: “-cd”
      • Push to stack → stack = [‘+ab’, ‘-cd’]
    8. Process ‘*’:
      • Pop two operands: operand2 = ‘-cd’, operand1 = ‘+ab’
      • Create new expression: “*+ab-cd”
      • Push to stack → stack = [‘*+ab-cd’]
    9. Final result: “*+ab-cd”

    This prefix expression correctly represents the computation encoded in the original postfix expression “ab+cd-“, which means “(a+b)(c-d)” in infix notation.

    Edge Cases to Consider

    1. Empty Input: The algorithm would attempt to access an empty stack, causing an error. Input validation should be added.
    2. Single Operand: For input like “a”, the output would just be “a”, which is correct.
    3. Invalid Postfix Expression: If the input isn’t a valid postfix expression (e.g., not enough operands for operators), the algorithm will fail when attempting to pop from the stack.
    4. Complex Expressions: The algorithm handles arbitrarily complex expressions correctly, as long as they are valid postfix expressions.
    5. Multi-Character Operands: The current implementation assumes single-character operands. For multi-character operands, additional tokenization would be needed.

    Time and Space Complexity

    Time Complexity: O(n)

    • We iterate through the input string once, processing each character exactly once.
    • Each character is either pushed onto the stack once, or causes two pops and one push.
    • String concatenation operations are generally O(1) for small strings.
    • Overall, the time complexity is linear in the length of the input string.

    Space Complexity: O(n)

    • In the worst case, the stack might contain nearly all characters from the input.
    • Therefore, the space complexity is O(n), where n is the length of the input string.

    Applications

    Understanding postfix to prefix conversion has several practical applications:

    1. Compiler Design: Compilers often convert between different notations during parsing and code generation.
    2. Expression Evaluators: Systems that work with multiple notation formats need conversion capabilities.
    3. Programming Language Tools: Some languages use different notations natively, requiring conversion for interoperability.
    4. Educational Tools: Teaching aids for computer science students learning about different expression notations.

    Prefix to Postfix Conversion Explanation

    Approach/Intuition

    Converting from prefix notation to postfix notation involves transforming expressions from a format where operators precede their operands (e.g., “+ab”) to one where operators follow their operands (e.g., “ab+”). Both notations are parenthesis-free and unambiguous, making them valuable in computer science for expression evaluation.

    The key insight for this conversion is that we need to process the prefix expression in reverse order (right to left). This approach works because:

    1. In prefix notation, operators come before operands
    2. When reading right to left, we encounter operands before their operators
    3. By using a stack and processing in reverse, we can build the postfix expression incrementally

    The algorithm follows these steps:

    1. Scan the prefix expression from right to left
    2. When an operand is encountered, push it onto the stack
    3. When an operator is encountered, pop the top two elements from the stack (these are operands)
    4. Create a new expression with the first operand, then the second operand, then the operator
    5. Push this new expression back onto the stack
    6. After processing the entire prefix expression, the stack will contain a single element – the complete postfix expression

    This approach elegantly handles the structural differences between prefix and postfix notations.

    Code

    class Solution:
        def preToPost(self, s):
            # Stack to store operands or partial postfix expressions
            stack = []
    
            # Traverse the prefix expression from right to left using index
            n = len(s)
            for i in range(n - 1, -1, -1):  # Reverse iteration using index
                char = s[i]
    
                # If the character is an operand, push it to the stack
                if char.isalnum():
                    stack.append(char)
                else:
                    # Pop two operands from the stack
                    operand1 = stack.pop()  # First operand
                    operand2 = stack.pop()  # Second operand
    
                    # Combine the operands with the operator in postfix form
                    new_expr = operand1 + operand2 + char
    
                    # Push the result back onto the stack
                    stack.append(new_expr)
    
            # The final element in the stack is the postfix expression
            return stack[-1]

    Code Explanation

    The implementation uses a single stack and processes the prefix expression from right to left:

    1. Stack Initialization: We create an empty list to serve as our stack for storing operands and intermediate expressions.
    2. Character Processing:
      • We iterate through the string in reverse order using range(n-1, -1, -1)
      • For each character:
        • If it’s an alphanumeric character (an operand), we push it directly onto the stack
        • If it’s an operator, we:
          • Pop the top element from the stack (first operand)
          • Pop the next element from the stack (second operand)
          • Combine them with the operator in postfix form: “operand1 operand2 operator”
          • Push this new expression back onto the stack
    3. Final Result: After processing all characters, the stack will contain exactly one element – the complete postfix expression.

    The key aspects of this implementation are:

    • Using isalnum() to identify operands (both letters and numbers)
    • Processing the string from right to left (crucial for correct conversion)
    • The order of operands in the formed expression: operand1 + operand2 + operator
    • Using string concatenation to build the postfix expression incrementally

    Dry Run Example

    Let’s trace through the conversion of the prefix expression “*+ab-cd” to postfix:

    1. Initialize: stack = []
    2. Process (from right to left):
      • ‘d’: Push to stack → stack = [‘d’]
      • ‘c’: Push to stack → stack = [‘d’, ‘c’]
      • ‘-‘:
        • Pop two operands: operand1 = ‘c’, operand2 = ‘d’
        • Create new expression: “cd-“
        • Push to stack → stack = [‘cd-‘]
      • ‘b’: Push to stack → stack = [‘cd-‘, ‘b’]
      • ‘a’: Push to stack → stack = [‘cd-‘, ‘b’, ‘a’]
      • ‘+’:
        • Pop two operands: operand1 = ‘a’, operand2 = ‘b’
        • Create new expression: “ab+”
        • Push to stack → stack = [‘cd-‘, ‘ab+’]
      • ‘*’:
        • Pop two operands: operand1 = ‘ab+’, operand2 = ‘cd-‘
        • Create new expression: “ab+cd-*”
        • Push to stack → stack = [‘ab+cd-*’]
    3. Final result: “ab+cd-*”

    This postfix expression correctly represents the computation encoded in the original prefix expression “+ab-cd”, which means “(a+b)(c-d)” in infix notation.

    Edge Cases to Consider

    1. Empty Input: The algorithm would attempt to access an empty stack, causing an error. Input validation should be added.
    2. Single Operand: For input like “a”, the output would just be “a”, which is correct.
    3. Invalid Prefix Expression: If the input isn’t a valid prefix expression (e.g., not enough operands for operators), the algorithm will fail when attempting to pop from the stack.
    4. Complex Expressions: The algorithm handles arbitrarily complex expressions correctly, as long as they are valid prefix expressions.
    5. Multi-Character Operands: The current implementation assumes single-character operands. For multi-character operands, additional tokenization would be needed.

    Time and Space Complexity

    Time Complexity: O(n)

    • We iterate through the input string once, processing each character exactly once.
    • Each character is either pushed onto the stack once, or causes two pops and one push.
    • String concatenation operations are generally O(1) for small strings.
    • Overall, the time complexity is linear in the length of the input string.

    Space Complexity: O(n)

    • In the worst case, the stack might contain nearly all characters from the input.
    • The final postfix expression will be roughly the same size as the input prefix expression.
    • Therefore, the space complexity is O(n), where n is the length of the input string.

    Applications

    The ability to convert between prefix and postfix notations has several practical applications:

    1. Compiler Design: Compilers often convert between different notations during different phases of compilation.
    2. Expression Evaluators: Systems that support multiple input formats may need to convert to a standard internal format.
    3. Calculator Implementations: Calculators might use one notation internally but need to display or accept input in different formats.
    4. Programming Language Tools: Tools for languages that natively use prefix notation (like LISP) or postfix notation might need conversion capabilities.
    Join our Advance DSA COURSE

    For any changes to the article, kindly email at code@codeanddebug.in or contact us at +91-9712928220.

    Easy Stack and Queues
    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Previous ArticleMin Stack | Leetcode 155 | Optimal Solution in Python
    codeanddebug
    • Website

    Related Posts

    Data Structures & Algorithms

    Min Stack | Leetcode 155 | Optimal Solution in Python

    6 August 2025
    Data Structures & Algorithms

    Valid Parentheses | Leetcode 20 | Stack implementation

    6 August 2025
    Data Structures & Algorithms

    Queue using Linked List | Complete Guide in Python

    6 August 2025
    Add A Comment
    Leave A Reply Cancel Reply

    Categories
    • Data Structures & Algorithms (174)
      • Beginner (67)
      • Expert (39)
      • Intermediate (68)
    • Uncategorised (1)
    Recent Posts

    Infix, Postfix, Prefix Conversions explained in Python

    6 August 2025

    Min Stack | Leetcode 155 | Optimal Solution in Python

    6 August 2025

    Valid Parentheses | Leetcode 20 | Stack implementation

    6 August 2025

    Queue using Linked List | Complete Guide in Python

    6 August 2025

    Stack using Linked List | Optimal Solution

    6 August 2025
    Facebook Instagram YouTube LinkedIn WhatsApp
    © 2025 Code and Debug. All rights reserved.

    Type above and press Enter to search. Press Esc to cancel.