0% found this document useful (0 votes)
2 views10 pages

Introduction to Stack

A stack is a linear data structure that operates on the Last In, First Out (LIFO) principle, commonly used for managing function calls, evaluating expressions, and undoing operations. It can be implemented using either an array or a linked list, with basic operations including push, pop, peek, isEmpty, and isFull. Stacks have various applications in programming, such as expression evaluation, function call management, and memory management.

Uploaded by

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

Introduction to Stack

A stack is a linear data structure that operates on the Last In, First Out (LIFO) principle, commonly used for managing function calls, evaluating expressions, and undoing operations. It can be implemented using either an array or a linked list, with basic operations including push, pop, peek, isEmpty, and isFull. Stacks have various applications in programming, such as expression evaluation, function call management, and memory management.

Uploaded by

RK
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Introduction to Stack in Data Structures

A stack is a linear data structure that follows the Last In, First Out (LIFO) principle, meaning
the last element added to the stack is the first one to be removed. It is widely used in
programming for tasks like managing function calls, evaluating expressions, and undoing
operations in applications.

Characteristics of a Stack

●​ LIFO Principle: The element inserted last is the first to be removed.

●​ One End Operations: Elements can be added (pushed) or removed (popped) only
from the top of the stack.

●​ Fixed Size or Dynamic: Depending on implementation, stacks can have a fixed size
(array-based) or be dynamic in size (linked list-based).

Basic Operations on a Stack

●​ Push: Add an element to the top of the stack.


●​ Pop: Remove the top element from the stack.
●​ Peek/Top: Retrieve the top element without removing it.
●​ isEmpty: Check if the stack is empty.
●​ isFull: Check if the stack is full (only for array-based implementations).

Representation of a Stack

Stacks can be implemented in two ways:

Array-Based Stack:
●​ Uses a fixed-size array.
●​ Simple to implement but has a limitation of a fixed size.

Linked List-Based Stack:


●​ Dynamic in size.
●​ Each element (node) has a value and a pointer to the next node.

Stack Operations in Detail

1. Push Operation

Adds an element to the top of the stack.


Steps:
Check if the stack is full (in array implementation).
Increment the top pointer.
Insert the element at the position pointed by top.
2. Pop Operation

Removes the top element of the stack.


Steps:
Check if the stack is empty.
Retrieve the element at the position pointed by top.
Decrement the top pointer.

3. Peek Operation

Retrieves the top element without removing it.


Steps:
Check if the stack is empty.
Return the value at the position pointed by top.

4. isEmpty Operation

Checks if the stack has no elements.


Steps:
Return true if top == -1; otherwise, return false.
Algorithmic Example

Push Operation

PUSH(stack, element, maxSize):

if TOP == maxSize – 1:

print “Stack Overflow”

else:

TOP = TOP + 1

stack[TOP] = element

Pop Operation

POP(stack):

if TOP == -1:

print “Stack Underflow”

else:

element = stack[TOP]
TOP = TOP – 1

return element

Applications of Stacks

1.​ Function Call Management: Used in recursion and backtracking.


2.​ Expression Evaluation:
●​ Infix to Postfix/Prefix Conversion.
●​ Evaluating Postfix/Prefix expressions.
3.​ Undo/Redo Mechanism: Common in text editors and software.
4.​ Balancing Parentheses: Validating expressions with brackets.
5.​ Browser History Navigation: Managing forward and backward navigation.

Advantages of Stacks

●​ Simple to implement.
●​ Efficient for LIFO operations.
●​ Useful in solving problems like parsing, recursion, and backtracking.

Limitations of Stacks

●​ Limited size in array-based implementation.


●​ Access is restricted to the top element only.

Example

Stack Push and Pop Example

Suppose a stack has a capacity of 5 and is initially empty:

Push 10 → Stack: [10]


Push 20 → Stack: [10, 20]
Push 30 → Stack: [10, 20, 30]
Pop → Removed 30; Stack: [10, 20]
Peek → Top element is 20.

Visualization

A stack can be visualized as a stack of plates where:

●​ Adding a plate is analogous to the push operation.


●​ Removing the top plate is analogous to the pop operation.

Stack using Array

A stack is a linear data structure that follows the Last-In-First-Out (LIFO) principle. It can be
implemented using an array by treating the end of the array as the top of the stack.
Declaration of Stack using Array

●​ A stack can be implemented using an array where we maintain:


●​ An integer array to store elements.
●​ A variable capacity to represent the maximum size of the stack.
●​ A variable top to track the index of the top element. Initially, top = -1 to indicate an
empty stack.

Full Implementation of Stack using Array

#include <iostream>
using namespace std;

class myStack {

// array to store elements


int *arr;

// maximum size of stack


int capacity;

// index of top element


int top;

public:

// constructor
myStack(int cap) {
capacity = cap;
arr = new int[capacity];
top = -1;
}

// push operation
void push(int x) {
if (top == capacity - 1) {
cout << "Stack Overflow\n";
return;
}
arr[++top] = x;
}

// pop operation
int pop() {
if (top == -1) {
cout << "Stack Underflow\n";
return -1;
}
return arr[top--];
}

// peek (or top) operation


int peek() {
if (top == -1) {
cout << "Stack is Empty\n";
return -1;
}
return arr[top];
}

// check if stack is empty


bool isEmpty() {
return top == -1;
}

// check if stack is full


bool isFull() {
return top == capacity - 1;
}
};

int main() {
myStack st(4);

// pushing elements
[Link](1);
[Link](2);
[Link](3);
[Link](4);

// popping one element


cout << "Popped: " << [Link]() << "\n";

// checking top element


cout << "Top element: " << [Link]() << "\n";

// checking if stack is empty


cout << "Is stack empty: " << ([Link]() ? "Yes" : "No") << "\n";

// checking if stack is full


cout << "Is stack full: " << ([Link]() ? "Yes" : "No") << "\n";

return 0;
}
Output

Popped: 4
Top element: 3
Is stack empty: No
Is stack full: No

​Stack - Linked List Implementation

A stack is a linear data structure that follows the Last-In-First-Out (LIFO) principle. It can be
implemented using a linked list, where each element of the stack is represented as a node.
The head of the linked list acts as the top of the stack.

Declaration of Stack using Linked List

A stack can be implemented using a linked list where we maintain:

●​ A Node structure/class that contains:


●​ data → to store the element.
●​ next → pointer/reference to the next node in the stack.
●​ A pointer/reference top that always points to the current top node of the stack.
●​ Initially, top = null to represent an empty stack.

Stack Implementation using Linked List

#include <iostream>
using namespace std;

// Node structure
class Node {
public:
int data;
Node* next;

Node(int x) {
data = x;
next = NULL;
}
};

// Stack implementation using linked list


class myStack {
Node* top;

// To Store current size of stack


int count;
public:
myStack() {

// initially stack is empty


top = NULL;
count = 0;
}

// push operation
void push(int x) {
Node* temp = new Node(x);
temp->next = top;
top = temp;

count++;
}

// pop operation
int pop() {
if (top == NULL) {
cout << "Stack Underflow" << endl;
return -1;
}
Node* temp = top;
top = top->next;
int val = temp->data;

count--;
delete temp;
return val;
}

// peek operation
int peek() {
if (top == NULL) {
cout << "Stack is Empty" << endl;
return -1;
}
return top->data;
}

// check if stack is empty


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

// size of stack
int size() {
return count;
}
8};

int main() {
myStack st;

// pushing elements
[Link](1);
[Link](2);
[Link](3);
[Link](4);

// popping one element


cout << "Popped: " << [Link]() << endl;

// checking top element


cout << "Top element: " << [Link]() << endl;

// checking if stack is empty


cout << "Is stack empty: " << ([Link]() ? "Yes" : "No") << endl;

// checking current size


cout << "Current size: " << [Link]() << endl;

return 0;
}

Output
Popped: 4
Top element: 3
Is stack empty: No
Current size: 3

Applications of Stack

Stacks are versatile and used in many areas of computer science and real-world
applications. Here are some common applications:

1. Expression Evaluation and Conversion

Infix to Postfix/Prefix Conversion: Stacks are used to convert infix expressions (e.g., A + B *
C) to postfix (e.g., ABC*+) or prefix (e.g., +A*BC).
Expression Evaluation: Postfix or prefix expressions are evaluated using stacks.

2. Function Call Management (Recursion)


The call stack in programming languages stores information about function calls.
It tracks return addresses, local variables, and parameters for recursive or nested function
calls.

3. Undo and Redo Operations

Text editors and applications use stacks to manage undo (reverting to the previous state)
and redo (reapplying an undone action) operations.

4. Browser History

A browser’s back and forward navigation system uses two stacks:


One stack for back history.
Another stack for forward history.

5. Parsing

Stacks are used in parsing operations, such as:


Syntax parsing in compilers to check matching parentheses or braces.
Processing XML or HTML tags to ensure proper nesting.

6. Tower of Hanoi

Stacks are used to simulate or solve the Tower of Hanoi puzzle efficiently.

7. Balancing Symbols

Stacks are employed to check if symbols in a string (e.g., {}, [], ()) are balanced correctly, like
in mathematical expressions or code.

8. Depth-First Search (DFS)

DFS in graph traversal uses stacks to explore nodes and backtrack when needed.
9. Memory Management

Operating systems use stacks for memory allocation in processes, particularly in managing
stack frames for functions.

10. Backtracking Algorithms

Stacks are used in backtracking problems, such as:


Solving mazes.
N-Queens problem.
Sudoku solving.

Multiple Stacks
Sometimes, applications require maintaining multiple stacks within the same memory space,
such as for managing multiple processes or tasks. Instead of creating separate arrays for
each stack, a single array can be divided dynamically or statically to store multiple stacks.

Approaches for Multiple Stacks

1.​ Fixed Partitioning:


●​ Divide the array into fixed sections, one for each stack.
●​ Requires prior knowledge of the maximum size each stack might need.
●​ Risk: Some stacks may overflow while others remain underutilized.

2.​ Dynamic Partitioning:


●​ Allow stacks to grow dynamically by overlapping their boundaries.
●​ Use additional metadata to manage free space and stack boundaries.

Implementation of Multiple Stacks as Queues

When multiple stacks need to function as separate queues within a single memory array, a
strategic implementation is required. This can be done using fixed partitioning or dynamic
partitioning methods.

Here’s a detailed explanation and implementation:

1. Concept of Multiple Stacks as Queues

To implement multiple queues using stacks:

●​ Each queue uses two stacks.


Stack 1 (Input Stack): Used for enqueue operations (pushing elements).
Stack 2 (Output Stack): Used for dequeue operations (retrieving elements).
●​ Queues are managed independently.

2. Operations in Each Queue

●​ Enqueue:
Push the element into Stack 1.
●​ Dequeue:
If Stack 2 is empty, transfer all elements from Stack 1 to Stack 2.
Pop the top element from Stack 2.

Applications of Multiple Stacks as Queues

●​ Process Scheduling: Managing independent task queues.


●​ Simulation: Modeling scenarios requiring FIFO behavior.
●​ Communication Systems: Handling multiple message queues in parallel.

You might also like