Applications of Stacks

Applications of Stacks

·

18 min read

Table of contents

Expression Conversion and evaluation–corresponding algorithms and complexity analysis.

Levels of Precedence of Arithmetic Operations

In arithmetic expressions, operator precedence determines the order in which operations are performed. Operators with higher precedence are executed before those with lower precedence. If two operators have the same precedence, their associativity determines the evaluation order.

Levels of Precedence

LevelOperatorsTypeAssociativityExample
1(), []ParenthesesLeft-to-Right(2 + 3) * 4 = 20
2^ (Exponentiation)PowerRight-to-Left2 ^ 3 ^ 2 = 2 ^ (3 ^ 2)
3*, /, %Multiplication, Division, ModulusLeft-to-Right6 / 3 * 2 = 4
4+, -Addition, SubtractionLeft-to-Right5 + 3 - 2 = 6

Summary of Rules

  1. Parentheses () have the highest precedence.

  2. Exponentiation ^ is next with right-to-left associativity.

  3. Multiplication *, Division /, and Modulus % share the same precedence and are evaluated left-to-right.

  4. Addition + and Subtraction - have the lowest precedence and are also left-to-right.

Polish Notations

  1. Introduction

    • Stacks are frequently used in the evaluation of arithmetic expressions.

    • Arithmetic expressions consist of:

      • Operands: Numeric values or variables.

      • Operators: Represent operations such as addition, subtraction, multiplication, division, and exponentiation.

  2. Problem in Early Programming

    • Converting a complex arithmetic expression like X = A / B + C * D – F * G / Q into correct machine instructions was challenging.

    • Each operator is assigned a priority to determine the order of evaluation.

  3. Polish Notation

    • Introduced by a Polish mathematician as an alternative to represent arithmetic expressions.

    • Polish notation eliminates the need for parentheses to indicate the order of operations.

    • Types of Polish Notation:

      1. Prefix Notation

      2. Postfix Notation

  4. Prefix Notation

    • The operator is written before the operands.

    • Example: + AB

      • Here, + is written before operands A and B.
    • Prefix means "before".

  5. Postfix Notation

    • The operator is written after the operands.

    • Example: AB +

      • Here, + is written after operands A and B.
    • Postfix means "after".

  6. Infix Notation

    • The operator is written between the operands.

    • Example: A + B

      • Here, + is written between operands A and B.
    • This is the common notation used in general mathematics.

    • Infix means the operator is "in-between" the operands.


Summary of Polish Notations

TypePosition of OperatorExample
Prefix NotationBefore operands+ AB
Postfix NotationAfter operandsAB +
Infix NotationBetween operandsA + B

Reverse Polish Notation (RPN)

Reverse Polish Notation (RPN) is a form of Postfix Notation where the operator comes after the operands. It eliminates the need for parentheses to define the order of operations because the position of the operator determines the sequence of execution

Key Differences

AspectPostfix NotationReverse Polish Notation (RPN)
TerminologyGeneral mathematical notation.Specific to computing and calculators.
UsageTheoretical and mathematical use.Practical use in stack-based evaluation systems.
FocusConcept of placing operators after operands.Application and evaluation of Postfix using stacks.
ExampleAB +AB + (Same, but named RPN when applied in computing).

While Postfix Notation is a general term, Reverse Polish Notation (RPN) refers specifically to the computational implementation of Postfix Notation, widely used in calculators, compilers, and programming for its efficient evaluation mechanism.

NOTATION CONVERSIONS

1. Infix to Postfix Conversion

Algorithm:

  1. Initialize an empty stack for operators.

  2. Initialize an empty string for the result (postfix expression).

  3. Read the infix expression from left to right:

    • If the character is an operand (alphanumeric), append it to the result string.

    • If the character is an operator:

      • Pop operators from the stack to the result while they have higher or equal precedence than the current operator.

      • Push the current operator onto the stack.

    • If the character is a left parenthesis (, push it onto the stack.

    • If the character is a right parenthesis ), pop from the stack to the result until a left parenthesis ( is encountered, which is discarded.

  4. After reading the entire infix expression, pop all remaining operators from the stack to the result.

  5. The resulting string will be the postfix expression.

Pseudocode:

function infixToPostfix(infix):
    stack = empty stack
    postfix = empty string

    for each character c in infix:
        if c is operand:
            postfix = postfix + c
        else if c is '(':
            push '(' onto stack
        else if c is ')':
            while top of stack is not '(':
                postfix = postfix + pop from stack
            pop '(' from stack
        else if c is operator:
            while stack is not empty and precedence of top of stack >= precedence of current operator:
                postfix = postfix + pop from stack
            push current operator onto stack

    while stack is not empty:
        postfix = postfix + pop from stack

    return postfix

C Code (Infix to Postfix):

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define MAX 100

// Stack structure for operators
char stack[MAX];
int top = -1;

// Function to push an element onto the stack
void push(char value) {
    if (top < (MAX - 1)) {
        stack[++top] = value;
    } else {
        printf("Stack Overflow\n");
    }
}

// Function to pop an element from the stack
char pop() {
    if (top >= 0) {
        return stack[top--];
    } else {
        printf("Stack Underflow\n");
        return '\0';
    }
}

// Function to peek at the top element of the stack
char peek() {
    if (top >= 0)
        return stack[top];
    return '\0';
}

// Function to determine the precedence of operators
int precedence(char operator) {
    if (operator == '^')
        return 3;
    if (operator == '*' || operator == '/' || operator == '%')
        return 2;
    if (operator == '+' || operator == '-')
        return 1;
    return 0;
}

// Function to check if the character is an operator
int isOperator(char ch) {
    return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '^' || ch == '%');
}

// Function to convert infix to postfix
void infixToPostfix(char* infix, char* postfix) {
    int i = 0, j = 0;

    while (infix[i] != '\0') {
        char token = infix[i];

        // If token is an operand, add to the postfix result
        if (isalnum(token)) {
            postfix[j++] = token;
        }
        // If token is a left parenthesis, push onto stack
        else if (token == '(') {
            push(token);
        }
        // If token is a right parenthesis, pop until '(' is encountered
        else if (token == ')') {
            while (top >= 0 && peek() != '(') {
                postfix[j++] = pop();
            }
            pop(); // Pop '(' from the stack
        }
        // If token is an operator
        else if (isOperator(token)) {
            while (top >= 0 && precedence(peek()) >= precedence(token)) {
                postfix[j++] = pop();
            }
            push(token);
        }
        i++;
    }

    // Pop all remaining operators from the stack
    while (top >= 0) {
        postfix[j++] = pop();
    }

    postfix[j] = '\0'; // Null-terminate the postfix string
}

// Main function to test the code
int main() {
    char infix[100], postfix[100];

    printf("Enter an infix expression: ");
    scanf("%s", infix);

    infixToPostfix(infix, postfix);

    printf("Postfix Expression: %s\n", postfix);
    return 0;
}

Example:

Input:

A+B*C-D

Conversion Steps:

StepTokenStackPostfix Expression
1AA
2++A
3B+AB
4*+ *AB
5C+ *ABC
6--ABC*+
7D-ABC*+D
8EndABC*+D-

Output:

Postfix Expression: ABC*+D-

2. Infix to Prefix Conversion

Algorithm:

  1. Reverse the infix expression.

  2. Replace each ( with ) and each ) with (.

  3. Use the infix to postfix conversion algorithm on the modified expression.

  4. Reverse the resulting postfix expression to get the prefix expression.

Pseudocode:

kotlinCopy codefunction infixToPrefix(infix):
    reverse infix expression
    for each character c in reversed infix:
        if c is '(' then change to ')'
        if c is ')' then change to '('

    postfix = infixToPostfix(reversed infix)
    reverse postfix to get prefix
    return prefix

C Code (Infix to Prefix):

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#define MAX 100

// Stack structure for operators
char stack[MAX];
int top = -1;

// Function to push an element onto the stack
void push(char value) {
    if (top < (MAX - 1)) {
        stack[++top] = value;
    } else {
        printf("Stack Overflow\n");
    }
}

// Function to pop an element from the stack
char pop() {
    if (top >= 0) {
        return stack[top--];
    } else {
        printf("Stack Underflow\n");
        return '\0';
    }
}

// Function to peek at the top element of the stack
char peek() {
    if (top >= 0)
        return stack[top];
    return '\0';
}

// Function to determine the precedence of operators
int precedence(char operator) {
    if (operator == '^')
        return 3;
    if (operator == '*' || operator == '/' || operator == '%')
        return 2;
    if (operator == '+' || operator == '-')
        return 1;
    return 0;
}

// Function to check if the character is an operator
int isOperator(char ch) {
    return (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '^');
}

// Function to reverse a string
void reverse(char* str) {
    int length = strlen(str);
    for (int i = 0, j = length - 1; i < j; i++, j--) {
        char temp = str[i];
        str[i] = str[j];
        str[j] = temp;
    }
}

// Function to convert infix to postfix
void infixToPostfix(char* infix, char* postfix) {
    int i = 0, j = 0;

    while (infix[i] != '\0') {
        char token = infix[i];

        if (isalnum(token)) {
            postfix[j++] = token;
        } else if (token == '(') {
            push(token);
        } else if (token == ')') {
            while (top >= 0 && peek() != '(') {
                postfix[j++] = pop();
            }
            pop(); // Pop '(' from the stack
        } else if (isOperator(token)) {
            while (top >= 0 && precedence(peek()) >= precedence(token)) {
                postfix[j++] = pop();
            }
            push(token);
        }
        i++;
    }

    while (top >= 0) {
        postfix[j++] = pop();
    }

    postfix[j] = '\0';
}

// Function to convert infix to prefix
void infixToPrefix(char* infix, char* prefix) {
    reverse(infix); // Step 1: Reverse the infix expression

    for (int i = 0; infix[i] != '\0'; i++) { // Step 2: Swap parentheses
        if (infix[i] == '(')
            infix[i] = ')';
        else if (infix[i] == ')')
            infix[i] = '(';
    }

    char postfix[MAX];
    infixToPostfix(infix, postfix); // Step 3: Convert the modified infix to postfix

    reverse(postfix); // Step 4: Reverse the postfix to get prefix
    strcpy(prefix, postfix);
}

int main() {
    char infix[100], prefix[100];

    printf("Enter an infix expression: ");
    scanf("%s", infix);

    infixToPrefix(infix, prefix);

    printf("Prefix Expression: %s\n", prefix);
    return 0;
}

Example (Infix to Prefix):

Infix Expression (input):

A+B*C-D

Step-by-Step Conversion:

StepTokenStackExpression
1-
Reverse the infix expression: A + B * C - DD - C * B + A
2DD
3--D
4C-DC
5*- *DC
6B- *DCB
7+- ** → pop to result, push +DCB*-
8A+DCB*-A
9-+ → pop + to resultDCB*-A+
10Reverse the postfix expression: DCB*-A++A*-BCD+A*-BCD

Final Prefix Expression:

+A*-BCD

Explanation:

  1. Step 1: Reverse the infix expression to handle it from right to left: A + B * C - D becomes D - C * B + A.

  2. Step 2: Start processing each token:

    • The first token is D, which is an operand, so it's added to the expression: D.
  3. Step 3: The next token is the operator -, which is pushed onto the stack: Stack: -.

  4. Step 4: Process operand C and add it to the expression: DC.

  5. Step 5: Next token is *, which has higher precedence than -. Push * onto the stack: Stack: - *.

  6. Step 6: Process operand B and add it to the expression: DCB.

  7. Step 7: Next token is +. Pop operators from the stack until an operator with lower precedence is found. Pop * and add it to the expression, then pop - and add it to the expression. Push + onto the stack: Stack: +, Postfix so far: DCB*-.

  8. Step 8: Process operand A and add it to the expression: DCB*-A.

  9. Step 9: Pop the remaining + from the stack and add it to the expression: DCB*-A+.

  10. Step 10: Finally, reverse the postfix expression DCB*-A+ to obtain the final prefix expression: + A * - B C D.

Conclusion:

  • Infix to Postfix: The algorithm processes the infix expression from left to right, pushing operators onto a stack based on their precedence and associativity, and constructs the postfix expression.

  • Infix to Prefix: We reverse the infix expression, apply the infix-to-postfix conversion on the reversed string, and reverse the result to obtain the prefix expression.

Evaluation of Expressions

1. Postfix Expression Evaluation

Algorithm

  1. Create an empty stack.

  2. Scan the postfix expression from left to right.

  3. For each symbol in the expression:

    • If it is an operand, push it onto the stack.

    • If it is an operator:

      1. Pop two operands from the stack.

      2. Apply the operator to the two operands.

      3. Push the result back onto the stack.

  4. At the end of the expression, the value left on the stack is the result.

Pseudocode

PostfixEvaluation(expression):
    Initialize an empty stack.

    For each symbol in expression:
        If symbol is an operand:
            Push symbol onto the stack.
        Else if symbol is an operator:
            Operand2 = Pop from stack
            Operand1 = Pop from stack
            Result = Perform operation (Operand1 operator Operand2)
            Push Result onto the stack.

    Result = Pop from stack
    Return Result

C Program

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

#define MAX 100

// Stack implementation
int stack[MAX];
int top = -1;

void push(int value) {
    if (top == MAX - 1) {
        printf("Stack Overflow\n");
        return;
    }
    stack[++top] = value;
}

int pop() {
    if (top == -1) {
        printf("Stack Underflow\n");
        exit(1);
    }
    return stack[top--];
}

int evaluatePostfix(char* expression) {
    for (int i = 0; expression[i] != '\0'; i++) {
        char symbol = expression[i];

        if (isdigit(symbol)) {
            push(symbol - '0'); // Convert char to int
        } else {
            int operand2 = pop();
            int operand1 = pop();
            switch (symbol) {
                case '+': push(operand1 + operand2); break;
                case '-': push(operand1 - operand2); break;
                case '*': push(operand1 * operand2); break;
                case '/': push(operand1 / operand2); break;
                default: printf("Invalid operator: %c\n", symbol); exit(1);
            }
        }
    }
    return pop();
}

int main() {
    char expression[] = "53+82-*"; // Example postfix expression
    printf("Result: %d\n", evaluatePostfix(expression));
    return 0;
}

Example for Postfix

Expression: 53+82-*

Evaluation Table:

SymbolStackOperation
55Push 5
35, 3Push 3
+8Pop 5,3 & Push (5 + 3) = 8
88, 8Push 8
28, 8, 2Push 2
-8, 6Pop 8,2 & Push (8 - 2) = 6
*48Pop8,6 & Push (8 * 6) = 48

Result: 48


2. Prefix Expression Evaluation

Algorithm

  1. Create an empty stack.

  2. Scan the prefix expression from right to left.

  3. For each symbol in the expression:

    • If it is an operand, push it onto the stack.

    • If it is an operator:

      1. Pop two operands from the stack.

      2. Apply the operator to the two operands.

      3. Push the result back onto the stack.

  4. At the end of the expression, the value left on the stack is the result.


Pseudocode

PrefixEvaluation(expression):
    Initialize an empty stack.

    For each symbol in expression (scanned from right to left):
        If symbol is an operand:
            Push symbol onto the stack.
        Else if symbol is an operator:
            Operand1 = Pop from stack
            Operand2 = Pop from stack
            Result = Perform operation (Operand1 operator Operand2)
            Push Result onto the stack.

    Result = Pop from stack
    Return Result

C Program

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

#define MAX 100

// Stack implementation
int stack[MAX];
int top = -1;

void push(int value) {
    if (top == MAX - 1) {
        printf("Stack Overflow\n");
        return;
    }
    stack[++top] = value;
}

int pop() {
    if (top == -1) {
        printf("Stack Underflow\n");
        exit(1);
    }
    return stack[top--];
}

int evaluatePrefix(char* expression) {
    int length = strlen(expression);

    for (int i = length - 1; i >= 0; i--) {
        char symbol = expression[i];

        if (isdigit(symbol)) {
            push(symbol - '0'); // Convert char to int
        } else {
            int operand1 = pop();
            int operand2 = pop();
            switch (symbol) {
                case '+': push(operand1 + operand2); break;
                case '-': push(operand1 - operand2); break;
                case '*': push(operand1 * operand2); break;
                case '/': push(operand1 / operand2); break;
                default: printf("Invalid operator: %c\n", symbol); exit(1);
            }
        }
    }
    return pop();
}

int main() {
    char expression[] = "-+5*38/82"; // Example prefix expression
    printf("Result: %d\n", evaluatePrefix(expression));
    return 0;
}

Example for Prefix

Expression: -+5*38/82

Evaluation Table:

SymbolStackOperation
22Push 2
82,8Push 8
/4Pop 8,2 & Push ( 8 / 2 )= 4
84,8Push 8
34,8,3Push 3
*4,24Pop 3,8 & Push (3 * 8) = 24
54,24,5Push 5
+4,29Pop 5,24 & Push(5 + 24) = 29
-25Pop 4,29 & Push(29 - 4) = 25

Result: 25

Practice question based on PYQ

1.Watch the example of this video , it’s beautifully explained in easiest way

2.Convert the following infix expression into postfix expression using the stack data structure with detailed explanation:

A - (B / C + (D % E F) / G) H

[MAKAUT - 2022]

Ans:

Infix Expression:

A - (B / C + (D % E F) / G) H


Conversion Table

Expression ElementStackPostfix
AA
--A
(- (A
B- (AB
/- (/AB
C- (/ABC
+- (+ABC/
(- (+ (ABC/
D- (+ (ABC/D
%- (+ (%ABC/D
E- (+ (%ABC/DE
*- (+ (*ABC/DE%
F- (+ (*ABC/DE%F
)- (+ABC/DE%F*
/- (+ /ABC/DE%F*
G- (+ /ABC/DE%F*G
)-ABC/DE%F*G/+
*(- *ABC/DE%F*G/+
H(- *ABC/DE%F*G/+H
)NULLABC/DE%F*G/+H*-

Final Postfix Expression

ABC/DE%F*G/+H*-

✨Self evaluation

for Below questions , at first try to do it then calculate the answer , now put the expression in corresponding conversion program and check converted result , now match it with your determined answer.

✨Some short type questions

( if anything you find wrong then let us know by commenting below )

1. What is an infix expression?

  • Answer: An infix expression is a mathematical expression where the operator is placed between operands (e.g., A + B).

2. What is a postfix expression?

  • Answer: A postfix expression (Reverse Polish Notation) is a mathematical expression where the operator comes after the operands (e.g., AB+).

3. What is a prefix expression?

  • Answer: A prefix expression (Polish Notation) is a mathematical expression where the operator comes before the operands (e.g., +AB).

4. Which data structure is used to evaluate postfix and prefix expressions?

  • Answer: Stack.

5. Why is the stack used for expression conversion?

  • Answer: A stack helps manage operator precedence, parentheses, and order of evaluation during conversion.

6. What is operator precedence?

  • Answer: Operator precedence determines the order in which operators are evaluated in an expression. For example, * has higher precedence than +.

7. What is operator associativity?

  • Answer: Operator associativity determines the direction (left-to-right or right-to-left) in which operators of the same precedence are evaluated.

8. What is the precedence order for arithmetic operators?

  • Answer: () > *, /, % > +, - (Parentheses > Multiplication/Division/Modulus > Addition/Subtraction).

9. Which notation does not require parentheses?

  • Answer: Postfix and prefix notations.

10. What is Reverse Polish Notation (RPN)?

  • Answer: Reverse Polish Notation is another name for postfix notation, where the operator follows the operands.

11. Convert A + B to postfix notation.

  • Answer: AB+.

12. Convert A + B to prefix notation.

  • Answer: +AB.

13. How do you evaluate a postfix expression?

  • Answer: Use a stack. Operands are pushed, and when an operator appears, values are popped, the operation is performed, and the result is pushed back.

14. What will be the postfix form of (A + B) * C?

  • Answer: AB+C*.

15. What will be the prefix form of (A + B) * C?

  • Answer: *+ABC.

16. State the difference between infix and postfix notation.

  • Answer:

    • Infix: Operators are between operands (e.g., A + B).

    • Postfix: Operators follow operands (e.g., AB+).


17. What is the postfix equivalent of A * B + C?

  • Answer: AB*C+.

18. Convert A + B * C to prefix notation.

  • Answer: +A*BC.

19. What happens when ) is encountered during infix to postfix conversion?

  • Answer: Operators are popped from the stack until ( is encountered.

20. Write the postfix form of A * (B + C).

  • Answer: ABC+*.