Chapter 1 Dsa
Chapter 1 Dsa
Overview
A stack is a linear data structure that follows the Last In, First
Out (LIFO) principle. This means that the last item added
(pushed) to the stack is the first one to be removed (popped).
Think of a stack like a pile of plates — you can only add or
remove the top plate.
Types of Stack:
Fixed Size Stack : As the name suggests, a fixed size
stack has a fixed size and cannot grow or shrink
dynamically. If the stack is full and an attempt is made to
add an element to it, an overflow error occurs. If the stack
is empty and an attempt is made to remove an element
from it, an underflow error occurs.
Dynamic Size Stack : A dynamic size stack can grow or
shrink dynamically. When the stack is full, it automatically
increases its size to accommodate the new element, and
when the stack is empty, it decreases its size. This type of
stack is implemented using a linked list, as it allows for
easy resizing of the stack.
Basic Operations
1. Push: Adds an element to the top of the stack.
2. Pop: Removes the top element from the stack.
3. Peek (Top): Returns the top element without removing it.
4. isEmpty: Checks if the stack is empty.
5. isFull (in some implementations): Checks if the stack
has reached its capacity.
1
Representation of Stack Data Structure:
Stack follows LIFO (Last In First Out) Principle so the element
which is pushed last is popped first.
Representation of Stack
struct stack {
type array[MAX_SIZE];
int top;
}
2
Chapter 2 : Operations
The key operations performed on a stack are:
1. Push: Adds an element to the top of the stack.
2. Pop: Removes the top element from the stack.
3. Peek/Top: Returns the top element of the stack without
removing it.
4. isEmpty: Checks if the stack is empty.
3
------------------------------------------------------------
---------------
Pop Operation
Definition: Removes and returns the top element of the stack
if it's not empty.
Function for pop operation is :
------------------------------------------------------------
---------------
Peek Operation
Definition: Returns the top element without removing it if the
stack is not empty.
4
return -1; // Sentinel value indicating error
}
return s->data[s->top];
}
------------------------------------------------------------
-------------
Check if Stack is Empty
Definition: Returns 1 (true) if the stack is empty, otherwise 0
(false).
Function to check if stack is empty :
5
------------------------------------------------------------
---------------
Display Stack
Definition: Displays all elements currently in the stack.
6
Program for the real life implementation of stack
in redo and undo function :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 5
#define ACTION_SIZE 50
7
return s->top == -1;
}
8
printf("Stack Underflow! No actions to undo.\
n");
return NULL;
}
return s->actions[(s->top)--];
}
9
printf("Current actions in stack: ");
for (int i = 0; i <= s->top; i++) {
printf("%s ", s->actions[i]);
}
printf("\n");
}
// Simulate actions
push(&undoStack, "Type 'Hello'");
push(&undoStack, "Type 'World'");
push(&undoStack, "Delete 'World'");
display(&undoStack);
11
// Perform Undo
undo(&undoStack, &redoStack);
display(&undoStack);
// Perform Redo
redo(&redoStack, &undoStack);
display(&undoStack);
return 0;
12
}
------------------------------------------------------------
---------------
Sample output :
Action 'Type 'Hello'' performed.
Action 'Type 'World'' performed.
Action 'Delete 'World'' performed.
Current actions in stack: Type 'Hello' Type 'World' Delete
'World'
Undo action: 'Delete 'World''
Current actions in stack: Type 'Hello' Type 'World'
Redo action: 'Delete 'World''
Current actions in stack: Type 'Hello' Type 'World' Delete
'World'
Action 'Type 'Stack'' performed.
Current actions in stack: Type 'Hello' Type 'World' Delete
'World' Type 'Stack'
Undo action: 'Type 'Stack''
Undo action: 'Delete 'World''
Current actions in stack: Type 'Hello' Type 'World'
13
Redo action: 'Delete 'World''
Redo action: 'Type 'Stack''
Current actions in stack: Type 'Hello' Type 'World' Delete
'World' Type 'Stack'
------------------------------------------------------------
---------------
Chapter 3 : Applications of
stack
Stacks are fundamental data structures with a wide
range of real-life applications, especially in situations
requiring a Last In, First Out (LIFO) approach. Two
common and significant applications of stacks involve
conversion tasks.
Here are two detailed examples:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
typedef struct {
char data[MAX];
int top;
} Stack;
15
}
16
// Function to return precedence of operators
int precedence(char op) {
if (op == '+' || op == '-') return 1;
if (op == '*' || op == '/') return 2;
return 0;
}
if (isalnum(ch)) {
postfix[j++] = ch;
} else if (ch == '(') {
push(&s, ch);
} else if (ch == ')') {
while (!isEmpty(&s) && peek(&s) != '(') {
postfix[j++] = pop(&s);
}
pop(&s); // Remove '(' from the stack
17
} else {
while (!isEmpty(&s) && precedence(peek(&s))
>= precedence(ch)) {
postfix[j++] = pop(&s);
}
push(&s, ch);
}
}
while (!isEmpty(&s)) {
postfix[j++] = pop(&s);
}
postfix[j] = '\0';
}
// Main function
int main() {
char infix[MAX];
char postfix[MAX];
infixToPostfix(infix, postfix);
18
printf("Postfix Expression: %s\n", postfix);
return 0;
}
Output:
Enter an infix expression: (A+B)*C-D
Postfix Expression: AB+C*D-
------------------------------------------------------------
---------------
2. Decimal to Binary Conversion
Background:
The stack can be used to convert a decimal number
to its binary equivalent. This process works by
continuously dividing the number by 2 and storing the
remainders (0 or 1) in a stack. When the division
process is complete, the binary number is obtained by
popping the remainders from the stack (since the
binary digits need to be read in reverse order).
Example:
Decimal Number: 13
o Steps:
13 / 2 → Quotient: 6, Remainder: 1
6 / 2 → Quotient: 3, Remainder: 0
3 / 2 → Quotient: 1, Remainder: 1
19
1 / 2 → Quotient: 0, Remainder: 1
o Binary: 1101
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int data[MAX];
int top;
} Stack;
20
int isEmpty(Stack *s) {
return s->top == -1;
}
if (num == 0) {
printf("Binary: 0\n");
return;
}
printf("Binary: ");
while (!isEmpty(&s)) {
printf("%d", pop(&s));
}
printf("\n");
}
// Main function
int main() {
int number;
decimalToBinary(number);
return 0;
}
Output :
22
Enter a decimal number: 13
Binary: 1101
------------------------------------------------------------
--------------
23
o Stacks are useful for reversing strings,
numbers, or other data since the last item
pushed is the first one popped.
5. Supports Undo/Redo Operations:
o Used in applications like text editors and
drawing applications to implement Undo/Redo
functionality.
6. Expression Evaluation and Parsing:
o Fundamental for evaluating or converting
mathematical expressions like infix to postfix
or evaluating postfix expressions.
7. Backtracking Algorithms:
o Useful in problems like maze solving, depth-
first search (DFS), and other backtracking
algorithms where returning to previous states
is necessary.
------------------------------------------------------------
---------------
Disadvantages of Stack
1. Limited Access:
o You can only access the top element of the
stack. Elements in the middle or bottom
cannot be accessed directly without popping
elements above them.
2. Fixed Size (in Array Implementation):
o If implemented using an array, the size of the
stack is fixed. This can lead to:
24
Stack Overflow if the stack exceeds its
capacity.
Wasted memory if the allocated size is too
large for the actual usage.
3. No Random Access:
o Unlike arrays or linked lists, stacks do not
allow random access to elements, which
makes certain operations inefficient.
4. Limited Flexibility:
o Stacks are suitable for specific tasks but not
ideal for general-purpose storage or
operations that require frequent access or
modifications to elements in the middle.
5. Risk of Overflow and Underflow:
o Stack Overflow occurs when pushing onto a
full stack.
o Stack Underflow occurs when popping from an
empty stack, potentially causing errors if not
handled properly.
6. Performance Issues in Some Scenarios:
o In cases where you need frequent insertion
and deletion from both ends, a deque (double-
ended queue) would be more efficient than a
stack.
------------------------------------------------------------
---------------
25