0% found this document useful (0 votes)
18 views23 pages

Unit 5

imp notes

Uploaded by

sayleebandal528
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views23 pages

Unit 5

imp notes

Uploaded by

sayleebandal528
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 23

Unit 5 (CHAPTER : 7) Stack

7.1 INTRODUCTION
A stack is a data structure that works like a stack of plates: you add (push) items on top and remove (pop)
items from the top. It follows a "Last In, First Out" (LIFO) rule, meaning the last item added is the first one to
be removed. Imagine stacking books: you can only take the top book without moving the others. Stacks are
used in many areas of programming, like tracking function calls or undo actions in apps.

7.2 Operations on Stack

1. Push

 Description: Adds an item to the top of the stack.


 Example:
o Initial Stack: [1, 2, 3]
o Operation: push(4)
o Resulting Stack: [1, 2, 3, 4]
 Explanation: 4 is added to the top of the stack.

2. Pop

 Description: Removes and returns the item at the top of the stack.
 Example:
o Initial Stack: [1, 2, 3, 4]
o Operation: pop()
o Result: Returns 4
o Resulting Stack: [1, 2, 3]
 Explanation: The top element 4 is removed and returned.

3. Peek (or Top)

 Description: Retrieves the item at the top of the stack without removing it.
 Example:
o Initial Stack: [1, 2, 3, 4]
o Operation: peek()
o Result: Returns 4
o Resulting Stack: [1, 2, 3, 4] (unchanged)
 Explanation: The top element 4 is accessed but not removed.

4. isEmpty

 Description: Checks if the stack is empty.


 Example:
o Initial Stack: [] (empty stack)
o Operation: isEmpty()
o Result: Returns true
 Explanation: Since there are no elements in the stack, isEmpty() returns true.

5. isFull

 Description: Checks if the stack has reached its maximum capacity (only applies to fixed-size stacks).
 Example:
o Assume Stack Capacity: 5
o Initial Stack: [1, 2, 3, 4, 5]
o Operation: isFull()
o Result: Returns true
 Explanation: Since the stack has 5 elements (its maximum capacity), isFull() returns true.

6. Size

 Description: Returns the number of items currently in the stack.


 Example:
o Initial Stack: [1, 2, 3, 4]
o Operation: size()
o Result: Returns 4
 Explanation: The stack has 4 elements, so size() returns 4.

7. Clear (or Make Empty)

 Description: Removes all elements from the stack, leaving it empty.


 Example:
o Initial Stack: [1, 2, 3, 4]
o Operation: clear()
o Resulting Stack: []
 Explanation: All elements are removed, making the stack empty.

8. Search

 Description: Searches for an item in the stack and returns its distance from the top (top element has
distance 1).
 Example:
o Initial Stack: [1, 2, 3, 4, 5]
o Operation: search(3)
o Result: Returns 3
 Explanation: The element 3 is 3 positions away from the top, so search(3) returns 3. If the item
isn’t found, it returns -1.

7.3 Array Representation


In an array representation of a stack, the stack is typically implemented using a fixed-size array where the
operations (push, pop, peek) modify the array's elements based on the stack's Last In, First Out (LIFO) order.

Key Points in Array Representation:

 Top of the stack: We maintain a variable (often called top) that points to the index of the top element
in the stack.
 Array: The stack is represented using an array where the elements are stored in consecutive positions.

Operations in Array Representation:

1. Push Operation:
o Adds an element to the stack. The element is inserted at the position indicated by the top
index.
o After the insertion, the top index is incremented.

java
Copy code
top++; // Increment top
stack[top] = element; // Place element at the top

2. Pop Operation:
o Removes the element from the top of the stack. The top index is decremented after removing
the element.

java
Copy code
element = stack[top]; // Get the top element
top--; // Decrease top

3. Peek Operation:
o Returns the element at the top of the stack without removing it.

java
Copy code
element = stack[top]; // Get the top element

4. IsEmpty Operation:
o Checks if the top is at -1 (indicating an empty stack).

java
Copy code
if (top == -1) {
// Stack is empty
}

Visualization:

If the stack array is of size 5 and contains elements [1, 2, 3] with top = 2, it would look like this:

Index 0 1 2 3 4
Value 1 2 3 _ _
Top ↑

 The top pointer points to index 2, which contains the element 3.


 If we push 4, the array would be updated to:

Index 0 1 2 3 4
Value 1 2 3 4 _
Top ↑

The stack array is full when the top equals maxSize - 1.

C++ Implementation of Stack using Array


cpp
Copy code
#include <iostream>
using namespace std;

class Stack {
private:
int maxSize;
int top;
int* stackArray;

public:
// Constructor to initialize the stack
Stack(int size) {
maxSize = size;
stackArray = new int[size];
top = -1; // Stack is empty initially
}

// Destructor to free the allocated memory


~Stack() {
delete[] stackArray;
}

// Push operation
void push(int element) {
if (top < maxSize - 1) {
stackArray[++top] = element; // Increment top and add element
} else {
cout << "Stack Overflow" << endl;
}
}

// Pop operation
int pop() {
if (top == -1) {
cout << "Stack Underflow" << endl;
return -1; // Indicating underflow
} else {
return stackArray[top--]; // Return top element and decrement top
}
}

// Peek operation
int peek() {
if (top != -1) {
return stackArray[top]; // Return top element
} else {
cout << "Stack is empty" << endl;
return -1; // Indicating empty stack
}
}

// IsEmpty operation
bool isEmpty() {
return top == -1; // Stack is empty if top is -1
}
};

int main() {
Stack stack(5); // Create stack of size 5

stack.push(10);
stack.push(20);
stack.push(30);

cout << "Top element is " << stack.peek() << endl; // Should output 30

stack.pop(); // Removes 30
cout << "Top element after pop is " << stack.peek() << endl; // Should output 20

return 0;
}

Program Showing Stack Operation

#include <iostream>
using namespace std;

class Stack {
private:
int maxSize;
int top;
int* stackArray;

public:
// Constructor to initialize the stack
Stack(int size) {
maxSize = size;
stackArray = new int[size];
top = -1; // Stack is empty initially
}

// Destructor to free the allocated memory


~Stack() {
delete[] stackArray;
}

// Push operation: Adds an element to the stack


void push(int element) {
if (top < maxSize - 1) {
stackArray[++top] = element; // Increment top and add element
cout << "Pushed " << element << " to stack" << endl;
} else {
cout << "Stack Overflow!" << endl;
}
}

// Pop operation: Removes and returns the top element


int pop() {
if (top == -1) {
cout << "Stack Underflow!" << endl;
return -1; // Indicating underflow
} else {
cout << "Popped " << stackArray[top] << " from stack" <<
endl;
return stackArray[top--]; // Return top element and decrement
top
}
}

// Peek operation: Returns the top element without removing it


int peek() {
if (top != -1) {
return stackArray[top]; // Return top element
} else {
cout << "Stack is empty!" << endl;
return -1; // Indicating empty stack
}
}

// IsEmpty operation: Returns true if the stack is empty


bool isEmpty() {
return top == -1; // Stack is empty if top is -1
}

// Display the current stack elements (for demonstration)


void display() {
if (top == -1) {
cout << "Stack is empty!" << endl;
} else {
cout << "Stack contents: ";
for (int i = 0; i <= top; i++) {
cout << stackArray[i] << " ";
}
cout << endl;
}
}
};

int main() {
Stack stack(5); // Create stack with a maximum size of 5

// Perform stack operations


stack.push(10);
stack.push(20);
stack.push(30);
stack.push(40);
stack.push(50);
stack.push(60); // This should cause stack overflow

stack.display(); // Show current stack contents


cout << "Top element is: " << stack.peek() << endl; // Peek at top
element

stack.pop(); // Pop top element


stack.pop(); // Pop next element
stack.display(); // Show updated stack contents

cout << "Top element after pops is: " << stack.peek() << endl; //
Peek after popping

return 0;
}

C++ Program for Stack Operations with Overflow and Underflow Handling:
#include <iostream>
using namespace std;

#define MAX_SIZE 5 // Define the maximum size of the stack

class Stack {
private:
int top;
int stackArray[MAX_SIZE];

public:
// Constructor to initialize the stack
Stack() {
top = -1; // Stack is empty initially
}

// Push operation: Adds an element to the stack


void push(int element) {
if (top == MAX_SIZE - 1) {
cout << "Stack Overflow! Cannot push " << element << endl;
// Stack is full
} else {
stackArray[++top] = element; // Increment top and add the
element
cout << "Pushed " << element << " to stack" << endl;
}
}

// Pop operation: Removes and returns the top element


int pop() {
if (top == -1) {
cout << "Stack Underflow! Cannot pop from an empty stack" <<
endl;
return -1; // Stack is empty
} else {
return stackArray[top--]; // Return top element and
decrement top
}
}

// Peek operation: Returns the top element without removing it


int peek() {
if (top != -1) {
return stackArray[top]; // Return top element
} else {
cout << "Stack is empty! Cannot peek" << endl;
return -1; // Stack is empty
}
}

// IsEmpty operation: Returns true if the stack is empty


bool isEmpty() {
return top == -1; // Stack is empty if top is -1
}

// Display operation: Displays the current elements in the stack


void display() {
if (top == -1) {
cout << "Stack is empty!" << endl;
} else {
cout << "Stack contents: ";
for (int i = 0; i <= top; i++) {
cout << stackArray[i] << " ";
}
cout << endl;
}
}
};

int main() {
Stack stack; // Create a stack object

// Perform stack operations


stack.push(10);
stack.push(20);
stack.push(30);
stack.push(40);
stack.push(50);
stack.push(60); // This will cause stack overflow

stack.display(); // Show current stack contents

cout << "Top element is: " << stack.peek() << endl; // Peek at top
element

cout << "Popped element: " << stack.pop() << endl; // Pop an element
cout << "Popped element: " << stack.pop() << endl; // Pop another
element
stack.display(); // Show updated stack contents

cout << "Top element after pops is: " << stack.peek() << endl; //
Peek after popping

return 0;
}

7.4 Linked Representation of a Stack


Here’s an implementation of a stack using a linked list in C++:

#include <iostream>
using namespace std;

// Node structure for Linked List


struct Node {
int data;
Node* next;
};

// Stack class using Linked List


class Stack {
private:
Node* top;

public:
Stack() {
top = nullptr;
}

// Push operation
void push(int value) {
Node* newNode = new Node;
newNode->data = value;
newNode->next = top;
top = newNode;
cout << value << " pushed to stack\n";
}

// Pop operation
int pop() {
if (top == nullptr) {
cout << "Stack is empty\n";
return -1;
}
int poppedValue = top->data;
Node* temp = top;
top = top->next;
delete temp;
return poppedValue;
}

// Peek operation (view top element)


int peek() {
if (top == nullptr) {
cout << "Stack is empty\n";
return -1;
}
return top->data;
}

// Check if stack is empty


bool isEmpty() {
return top == nullptr;
}

// Destructor to clean up the stack


~Stack() {
while (!isEmpty()) {
pop();
}
}
};

int main() {
Stack stack;

stack.push(10);
stack.push(20);
stack.push(30);

cout << stack.peek() << " is on top of the stack\n";

cout << stack.pop() << " popped from stack\n";

cout << stack.peek() << " is now on top of the stack\n";

return 0;
}

7.4.1 Functions for stack operation

Here are the basic stack operations in C++ implemented as individual functions. These operations include
push, pop, peek, isEmpty, and a constructor/destructor for managing the stack.

Stack Operations Functions:

#include <iostream>
using namespace std;

// Node structure for Linked List


struct Node {
int data;
Node* next;
};

// Push function to add an element to the stack


void push(Node*& top, int value) {
Node* newNode = new Node;
newNode->data = value;
newNode->next = top;
top = newNode;
cout << value << " pushed to stack\n";
}

// Pop function to remove the top element from the stack


int pop(Node*& top) {
if (top == nullptr) {
cout << "Stack is empty\n";
return -1;
}
int poppedValue = top->data;
Node* temp = top;
top = top->next;
delete temp;
return poppedValue;
}

// Peek function to view the top element of the stack without removing it
int peek(Node* top) {
if (top == nullptr) {
cout << "Stack is empty\n";
return -1;
}
return top->data;
}

// isEmpty function to check if the stack is empty


bool isEmpty(Node* top) {
return top == nullptr;
}

// Destructor function to clean up the stack memory


void destroyStack(Node*& top) {
while (!isEmpty(top)) {
pop(top);
}
}

int main() {
Node* top = nullptr; // Initialize stack

push(top, 10);
push(top, 20);
push(top, 30);

cout << peek(top) << " is on top of the stack\n";

cout << pop(top) << " popped from stack\n";

cout << peek(top) << " is now on top of the stack\n";

destroyStack(top); // Clean up the stack

return 0;
}

7.5 Applications of Stack

 Expression Evaluation: Used to evaluate mathematical expressions like 2 3 + 5 * (postfix notation) and
convert between infix and postfix expressions.

 Function Calls: Manages function calls and keeps track of the execution state (call stack).

 Undo/Redo: Keeps a history of actions in apps like text editors, so you can undo or redo actions.

 Backtracking: Helps in problems like maze solving or searching, where you backtrack to a previous state.

 Balanced Parentheses: Checks if symbols like (), {}, and [] are balanced in code or expressions.
 Depth-First Search (DFS): Used in algorithms to explore graphs and trees, by going as deep as possible
before backtracking.

 Memory Management: Manages local variable storage in the program, where memory is automatically
cleaned up when a function ends.

 Browser History: Keeps track of visited pages so you can use the back and forward buttons.

 Expression Parsing: Helps in programming languages to interpret and process expressions in code.

 Plate Stacking: Solves problems like the Tower of Hanoi, where disks or plates are moved between rods
using a stack.

Evaluation of postfix expression using a stack

To evaluate a postfix expression (also known as Reverse Polish Notation) using a stack, we follow these
simple steps:

1. Scan the Expression from Left to Right:


o If the element is a number (operand), push it onto the stack.
o If the element is an operator (+, -, *, /), pop the two top elements from the stack, apply the
operator, and push the result back onto the stack.

2. Result:
o After processing all elements, the result will be the single element left in the stack.

Example Walkthrough

Consider the postfix expression 5 3 2 * +.

1. Read 5: It's a number, so push 5 onto the stack.


o Stack: [5]

2. Read 3: It's a number, so push 3 onto the stack.


o Stack: [5, 3]

3. Read 2: It's a number, so push 2 onto the stack.


o Stack: [5, 3, 2]

4. Read *: It's an operator, so pop 2 and 3, multiply them (3 * 2 = 6), and push 6 back onto the
stack.
o Stack: [5, 6]

5. Read +: It's an operator, so pop 6 and 5, add them (5 + 6 = 11), and push 11 back onto the stack.
o Stack: [11]

The stack now contains only one element, 11, which is the final result.

C++ Code for Postfix Evaluation

Here's a C++ program that evaluates a postfix expression using a stack.

#include <iostream>
#include <stack>
#include <sstream>
using namespace std;

int evaluatePostfix(const string& expression) {


stack<int> s;
istringstream tokens(expression);

string token;
while (tokens >> token) {
if (isdigit(token[0])) {
// If it's a number, push onto the stack
s.push(stoi(token));
} else {
// Operator case: pop two numbers, apply the operator, and
push result
int operand2 = s.top(); s.pop();
int operand1 = s.top(); s.pop();

int result;
switch (token[0]) {
case '+': result = operand1 + operand2; break;
case '-': result = operand1 - operand2; break;
case '*': result = operand1 * operand2; break;
case '/': result = operand1 / operand2; break;
default: throw runtime_error("Unsupported operator");
}
s.push(result);
}
}
return s.top(); // Final result
}

int main() {
string postfixExpr = "5 3 2 * +";
cout << "Result of postfix expression '" << postfixExpr << "' is: "
<< evaluatePostfix(postfixExpr) << endl;
return 0;

Explanation of the Code:

1. Stack Setup: We use a stack to store numbers as we encounter them.


2. Token Processing:
o If a token is a number, it’s pushed onto the stack.
o If a token is an operator, we pop two numbers, perform the operation, and push the result
back.
3. Result: After processing the expression, the final result is the only element left in the stack.

7.5.3 Evaluation of prefix expression using a stack

To evaluate a prefix expression (also known as Polish Notation) using a stack, we follow these steps:

1. Scan the Expression from Right to Left:


o If the element is a number (operand), push it onto the stack.
o If the element is an operator (+, -, *, /), pop the two top elements from the stack, apply the
operator to these elements in the correct order, and push the result back onto the stack.

2. Result:
o After processing all elements, the result will be the single element left in the stack.

Example Walkthrough

Consider the prefix expression + 5 * 3 2.

1. Read 2: It's a number, so push 2 onto the stack.


o Stack: [2]

2. Read 3: It's a number, so push 3 onto the stack.


o Stack: [2, 3]

3. Read *: It's an operator, so pop 3 and 2, multiply them (3 * 2 = 6), and push 6 back onto the
stack.
o Stack: [6]

4. Read 5: It's a number, so push 5 onto the stack.


o Stack: [6, 5]

5. Read +: It's an operator, so pop 5 and 6, add them (5 + 6 = 11), and push 11 back onto the stack.
o Stack: [11]

The stack now contains only one element, 11, which is the final result.

C++ Code for Prefix Evaluation

Here’s a C++ program to evaluate a prefix expression using a stack.

#include <iostream>
#include <stack>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;

int evaluatePrefix(const string& expression) {


stack<int> s;
istringstream tokens(expression);
vector<string> tokenList;

// Read tokens and store them in a vector for reverse iteration


string token;
while (tokens >> token) {
tokenList.push_back(token);
}
reverse(tokenList.begin(), tokenList.end());

// Process each token from right to left


for (const auto& token : tokenList) {
if (isdigit(token[0])) {
// If it's a number, push onto the stack
s.push(stoi(token));
} else {
// Operator case: pop two numbers, apply the operator, and
push result
int operand1 = s.top(); s.pop();
int operand2 = s.top(); s.pop();

int result;
switch (token[0]) {
case '+': result = operand1 + operand2; break;
case '-': result = operand1 - operand2; break;
case '*': result = operand1 * operand2; break;
case '/': result = operand1 / operand2; break;
default: throw runtime_error("Unsupported operator");
}
s.push(result);
}
}
return s.top(); // Final result
}

int main() {
string prefixExpr = "+ 5 * 3 2";
cout << "Result of prefix expression '" << prefixExpr << "' is: "
<< evaluatePrefix(prefixExpr) << endl;
return 0;
}

Explanation of the Code:

1. Token List Setup: We first read each token into a vector and reverse the vector so we can process it
from right to left.
2. Token Processing:
o If a token is a number, it’s pushed onto the stack.
o If a token is an operator, we pop two numbers, apply the operator, and push the result back
onto the stack.
3. Result: After processing the expression, the final result is the single element remaining in the stack.

Example Output:

csharp
Copy code
Result of prefix expression '+ 5 * 3 2' is: 11

Conversion of an expression from infix to postfix

Steps to Convert Infix to Postfix

1. Read the Expression from Left to Right:


o If you see a letter or number (operand), add it directly to the result (postfix expression).
o If you see an operator (+, -, *, /):
 Check the stack. If there are operators with higher or equal precedence on the
stack, pop them off and add them to the result first.
 Then, push the current operator onto the stack.
o If you see an opening bracket ((), push it onto the stack (it just marks the start of a group).
o If you see a closing bracket ()):
 Pop everything from the stack and add it to the result until you reach an opening
bracket.
 Discard the opening bracket from the stack.
2. End of Expression:
o Once you’ve read the entire expression, pop any remaining operators on the stack and add
them to the result.

Example Walkthrough

Let's convert the infix expression A + B * C to postfix.

1. Read A: It’s a letter, so add it directly to the postfix result.


o Postfix: A

2. Read +: It’s an operator, so push it onto the stack.


o Stack: [+]

3. Read B: It’s a letter, so add it directly to the postfix result.


o Postfix: A B

4. Read *: It’s an operator. Since * has higher precedence than +, we push it onto the stack.
o Stack: [+, *]

5. Read C: It’s a letter, so add it directly to the postfix result.


o Postfix: A B C

6. End of Expression:
o Pop all operators from the stack to the postfix result.
o Pop * and then +.
o Final Postfix: A B C * +

Final Postfix Expression

The postfix expression is A B C * +.

This method ensures that operations are arranged in the correct order for postfix notation, where operators
appear after their operands.

Here's a C++ implementation of infix to postfix conversion using a stack

#include <iostream>
#include <stack>
#include <string>
using namespace std;

// Function to return precedence of operators


int precedence(char op) {
if (op == '+' || op == '-') return 1;
if (op == '*' || op == '/') return 2;
return 0;
}

// Function to perform infix to postfix conversion


string infixToPostfix(const string& infix) {
stack<char> s;
string postfix;

for (char ch : infix) {


if (isalnum(ch)) {
// If the character is an operand, add it to the postfix
expression
postfix += ch;
}
else if (ch == '(') {
// If the character is '(', push it to the stack
s.push(ch);
}
else if (ch == ')') {
// Pop and add to postfix until '(' is found
while (!s.empty() && s.top() != '(') {
postfix += s.top();
s.pop();
}
s.pop(); // Remove '(' from the stack
}
else {
// Operator encountered
while (!s.empty() && precedence(s.top()) >= precedence(ch)) {
postfix += s.top();
s.pop();
}
s.push(ch);
}
}

// Pop all remaining operators from the stack


while (!s.empty()) {
postfix += s.top();
s.pop();
}

return postfix;
}

int main() {
string infixExpr = "A+B*C";
cout << "Postfix expression for '" << infixExpr << "' is: "
<< infixToPostfix(infixExpr) << endl;
return 0;
}

Question ) CONVERT THE FOLLOWING EXPRESSION FROM INFIX TO POSTFIX USING A STACK
a && b || c || ! (e>f)

To convert the infix expression a && b || c || ! (e > f) to postfix using a stack, we’ll apply the
rules of precedence and associativity as we build the postfix expression.

Operators and Precedence Levels:

1. ! (Logical NOT): Highest precedence.


2. && (Logical AND): Medium precedence.
3. || (Logical OR): Lowest precedence.
4. >, <, >=, <= (Relational operators): Medium precedence, same as &&.
Conversion Steps:

Let's walk through each character in the expression and apply our rules.

Expression: a && b || c || ! (e > f)

1. Read a: It’s an operand, so add it to the postfix result.


o Postfix: a

2. Read &&: It’s an operator, and the stack is empty, so push it onto the stack.
o Stack: [&&]

3. Read b: It’s an operand, so add it to the postfix result.


o Postfix: a b

4. Read ||: It’s an operator with lower precedence than &&.


o Pop && from the stack (since it has higher precedence) and add it to the postfix result.
o Then push || onto the stack.
o Postfix: a b &&
o Stack: [||]

5. Read c: It’s an operand, so add it to the postfix result.


o Postfix: a b && c

6. Read ||: It’s an operator with equal precedence to the || already on the stack.
o Pop || from the stack and add it to the postfix result.
o Push the new || onto the stack.
o Postfix: a b && c ||
o Stack: [||]

7. Read !: It’s a unary operator (NOT) with the highest precedence, so push it onto the stack.
o Stack: [||, !]

8. Read (: It’s an opening parenthesis, so push it onto the stack to mark the beginning of a group.
o Stack: [||, !, (]

9. Read e: It’s an operand, so add it to the postfix result.


o Postfix: a b && c || e

10. Read >: It’s a relational operator. Push it onto the stack since there’s only ( above it.
o Stack: [||, !, (, >]

11. Read f: It’s an operand, so add it to the postfix result.


o Postfix: a b && c || e f

12. Read ): It’s a closing parenthesis, so pop from the stack until we encounter the opening parenthesis (.
o Pop > and add it to the postfix result.
o Remove ( from the stack.
o Postfix: a b && c || e f >
o Stack: [||, !]

13. End of Expression: Now we pop all remaining operators from the stack and add them to the postfix
result.
o Pop ! and add it to the postfix result.
o Pop || and add it to the postfix result.
o Final Postfix: a b && c || e f > ! ||

Final Postfix Expression

The postfix expression is:

css
Copy code
a b && c || e f > ! ||

This postfix expression evaluates in the correct order of precedence for logical and relational operators.

Conversion of an expression from postfix to


infix to

To convert a postfix expression to infix, we use a stack to gradually build the expression with the correct
placement of operators and parentheses.

Let's convert the postfix expression a b && c || e f > ! || to infix notation.

Steps for Converting Postfix to Infix

1. Initialize an empty stack.


2. Scan each element from left to right:
o If the element is an operand (like a, b, etc.), push it onto the stack.
o If the element is an operator, pop the required number of operands from the stack (two for
binary operators like &&, ||, >, and one for unary operators like !), combine them into an
infix expression with parentheses if necessary, and push the result back onto the stack.
3. Result: Once the entire expression is scanned, the stack will contain one element, which is the fully
converted infix expression.

Example Walkthrough

Given postfix expression: a b && c || e f > ! ||

Step-by-Step Conversion:

1. Read a: It’s an operand, so push it onto the stack.


o Stack: ["a"]

2. Read b: It’s an operand, so push it onto the stack.


o Stack: ["a", "b"]

3. Read &&: It’s a binary operator.


o Pop b and a from the stack.
o Create the expression (a && b) and push it back onto the stack.
o Stack: ["(a && b)"]

4. Read c: It’s an operand, so push it onto the stack.


o Stack: ["(a && b)", "c"]

5. Read ||: It’s a binary operator.


o Pop c and (a && b) from the stack.
o Create the expression ((a && b) || c) and push it back onto the stack.
o Stack: ["((a && b) || c)"]

6. Read e: It’s an operand, so push it onto the stack.


o Stack: ["((a && b) || c)", "e"]

7. Read f: It’s an operand, so push it onto the stack.


o Stack: ["((a && b) || c)", "e", "f"]

8. Read >: It’s a binary operator.


o Pop f and e from the stack.
o Create the expression (e > f) and push it back onto the stack.
o Stack: ["((a && b) || c)", "(e > f)"]

9. Read !: It’s a unary operator.


o Pop (e > f) from the stack.
o Create the expression (!(e > f)) and push it back onto the stack.
o Stack: ["((a && b) || c)", "(!(e > f))"]

10. Read ||: It’s a binary operator.


o Pop (!(e > f)) and ((a && b) || c) from the stack.
o Create the expression (((a && b) || c) || (!(e > f))) and push it back onto
the stack.
o Stack: ["(((a && b) || c) || (!(e > f)))"]

Final Infix Expression

The stack now contains a single element, which is our final infix expression:

css
Copy code
(((a && b) || c) || (!(e > f)))

This is the infix expression for the given postfix notation, with correct placement of operators and parentheses
for clarity and precedence.

1. Code for Infix to Postfix Conversion

#include <iostream>
#include <stack>
#include <string>
#include <cctype>
using namespace std;

// Function to return precedence of operators


int precedence(char op) {
if (op == '!' ) return 3; // Unary NOT has highest precedence
if (op == '&&') return 2; // Logical AND
if (op == '||') return 1; // Logical OR
return 0;
}

// Function to perform infix to postfix conversion


string infixToPostfix(const string& infix) {
stack<string> s;
string postfix;
for (size_t i = 0; i < infix.length(); i++) {
char ch = infix[i];

// If the character is a whitespace, skip it


if (isspace(ch)) continue;

// If the character is an operand (a-z, 0-9), add it to the


postfix expression
if (isalnum(ch)) {
postfix += ch;
postfix += " ";
}
else if (ch == '(') {
// If the character is '(', push it to the stack
s.push(string(1, ch));
}
else if (ch == ')') {
// Pop and add to postfix until '(' is found
while (!s.empty() && s.top() != "(") {
postfix += s.top() + " ";
s.pop();
}
s.pop(); // Remove '(' from the stack
}
else {
// For binary operators like &&, || and relational operators
string op(1, ch);

// Handle "&&" and "||" specifically as they are two-


character operators
if ((ch == '&' || ch == '|') && i + 1 < infix.length() &&
infix[i + 1] == ch) {
op += ch; // Concatenate the second character
i++; // Skip the next character
}

// For other operators, pop until stack top has lower


precedence
while (!s.empty() && precedence(s.top()[0]) >=
precedence(op[0])) {
postfix += s.top() + " ";
s.pop();
}
s.push(op);
}
}

// Pop all remaining operators from the stack


while (!s.empty()) {
postfix += s.top() + " ";
s.pop();
}
return postfix;
}

int main() {
string infixExpr = "a && b || c || ! (e > f)";
cout << "Postfix expression: " << infixToPostfix(infixExpr) << endl;
return 0;
}

2. Code for Postfix to Infix Conversion

#include <iostream>
#include <stack>
#include <string>
#include <cctype>
using namespace std;

// Function to check if a string is an operator


bool isOperator(const string& op) {
return (op == "&&" || op == "||" || op == "!" || op == ">" || op ==
"<" || op == ">=" || op == "<=");
}

// Function to convert postfix to infix expression


string postfixToInfix(const string& postfix) {
stack<string> s;
string operand;

for (size_t i = 0; i < postfix.length(); i++) {


char ch = postfix[i];

// Skip whitespaces
if (isspace(ch)) continue;

// If it's an operand, add it to a temporary string


if (isalnum(ch)) {
operand += ch;
}
else if (!operand.empty()) {
// If we complete an operand, push it onto the stack
s.push(operand);
operand.clear();
}

// Check if it’s an operator


if (isOperator(string(1, ch)) || ch == '!' || ch == '&' || ch ==
'|') {
string op(1, ch);

// Handle multi-character operators like && and ||


if ((ch == '&' || ch == '|') && i + 1 < postfix.length() &&
postfix[i + 1] == ch) {
op += ch;
i++;
}

if (op == "!") {
// Unary operator: pop one operand
string operand1 = s.top();
s.pop();
s.push("!(" + operand1 + ")");
} else {
// Binary operator: pop two operands
string operand2 = s.top(); s.pop();
string operand1 = s.top(); s.pop();
s.push("(" + operand1 + " " + op + " " + operand2 + ")");
}
}
}

return s.top(); // The final element in the stack is the full infix
expression
}

int main() {
string postfixExpr = "a b && c || e f > ! ||";
cout << "Infix expression: " << postfixToInfix(postfixExpr) << endl;
return 0;
}

You might also like