Stacks
Stacks
A stack is a linear data structure that follows the LIFO (Last In, First Out) principle, meaning
the last element added to the stack is the first one to be removed.
Characteristics of a Stack
1. Operations:
2. Real-World Examples:
3. Applications:
o Expression evaluation (infix, postfix, prefix).
import java.util.Stack;
stack.push(20);
stack.push(30);
Sample Output
Stack after pushes: [10, 20, 30]
Top element: 30
Popped: 30
Position of 10 in stack: 2
Custom Stack Implementation
If you want to implement your own stack, you can use an array or linked list.
Using Array
class Stack {
private int[] arr;
// Constructor
public Stack(int size) {
capacity = size;
top = -1;
// Push an element
if (isFull()) {
System.out.println("Stack Overflow!");
return;
arr[++top] = value;
// Pop an element
public int pop() {
if (isEmpty()) {
System.out.println("Stack Underflow!");
return -1;
}
return arr[top--];
return arr[top];
}
return -1;
stack.push(10);
stack.push(20);
stack.push(30);
Sample Output
10 pushed onto stack.
Top element: 30
Popped: 30
Popped: 20
Popped: 10
Stack Underflow!
Assignments
1. Reverse a String Using a Stack:
2. Balanced Parentheses:
class Stack {
capacity = size;
top = -1; // Stack is initially empty
}
return;
// Pop operation: Removes and returns the top element of the stack
if (isEmpty()) {
return -1;
if (isEmpty()) {
return stackArray[top];
if (isEmpty()) {
System.out.println("Stack is empty!");
return;
}
System.out.println();
}
}
// Main class to test the Stack implementation
stack.push(20);
stack.push(30);
stack.display();
stack.pop();
stack.pop();
stack.pop(); // Attempt to pop from an empty stack
stack.push(40);
stack.push(50);
stack.push(60);
stack.push(70);
stack.push(80);
stack.push(90); // Attempt to push into a full stack
}
2. Pop Operation:
o Removes and returns the top element of the stack.
4. Helper Methods:
5. Display Method:
o Iterates through the array from index 0 to top to print the stack elements.
Sample Output
10 pushed to the stack.
Stack elements: 10 20 30
Top element is: 30
30 popped from the stack.
Stack elements: 10 20
Key Points
The capacity of the stack is fixed in this implementation.
Practice Assignments
1. Dynamic Stack Implementation:
o Modify the above code to resize the stack array when it gets full.
2. Reverse a String:
3. Palindrome Check:
1. Every opening parenthesis ((, {, [) has a corresponding closing parenthesis (), }, ]).
Algorithm
1. Traverse the string character by character.
o Pop the top of the stack and ensure it matches the current closing parenthesis.
4. After traversing the string, check if the stack is empty. If not, it's unbalanced.
Code Implementation
import java.util.Stack;
stack.push(current);
}
// Check for closing brackets
if (stack.isEmpty()) {
return false;
}
// Pop the top element and check if it matches the current closing bracket
char top = stack.pop();
if (!isMatchingPair(top, current)) {
return false;
return stack.isEmpty();
o A stack is used to store opening brackets ((, {, [) as they appear in the string.
o When a closing bracket is encountered (), }, ]), the top of the stack is checked and
popped if it matches.
2. isMatchingPair Method:
o Ensures that the popped opening bracket corresponds to the current closing
bracket.
3. Edge Cases:
o If the string starts with a closing bracket, the stack will be empty, and the method
will return false.
o If the stack is not empty after processing the string, it indicates unmatched
opening brackets.
Sample Input/Output
Input:
{[()]} -> Balanced
Output:
{[()]} -> Balanced
Practice Assignments
1. Extend the Program:
2. Parentheses Count:
o Create a program that can suggest corrections for an unbalanced string (e.g., ({[}
→ ({[]})).
Infix: (3 + 4) * 5
Postfix: 3 4 + 5 *
To evaluate a postfix expression:
1. Traverse the expression from left to right.
Code Implementation
import java.util.Stack;
continue;
if (Character.isDigit(current)) {
// Convert character to integer and push
stack.push(current - '0');
else {
int operand2 = stack.pop(); // Second operand
switch (current) {
case '+':
stack.push(operand1 + operand2);
break;
case '-':
stack.push(operand1 - operand2);
break;
case '*':
stack.push(operand1 * operand2);
break;
case '/':
stack.push(operand1 / operand2);
break;
default:
// The final result will be the only element left in the stack
return stack.pop();
o The stack is used to temporarily store operands. Operators act on these operands
to produce intermediate results, which are also stored on the stack.
2. Operands:
3. Operators:
o When an operator is encountered, the top two elements of the stack are popped.
o The operation is performed, and the result is pushed back onto the stack.
4. Final Result:
o After processing the entire expression, the stack contains only one element, which
is the final result.
5. Edge Cases:
o The expression must be valid. If the stack is empty or contains less than two
elements during an operator evaluation, an error will occur.
Sample Input/Output
Input:
Expression: "3 4 + 5 *"
Output:
Result of '3 4 + 5 *' is: 35
Input:
Expression: "6 3 / 2 * 1 +"
Output:
Result of '6 3 / 2 * 1 +' is: 5
Practice Assignments
1. Support Floating Point Numbers:
o Add error handling for cases like division by zero or invalid expressions.
4. Operator Precedence: