0% found this document useful (0 votes)
13 views44 pages

Lecture 4 - Stack

This document covers the Stack Abstract Data Type (ADT), including its definition, operations, and implementations using dynamic arrays and linked structures. It discusses various applications of stacks, such as function call management, expression evaluation, and symbol balancing. Additionally, it provides code examples for implementing stack operations and solving problems using stacks in C++.

Uploaded by

Nona Amir
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)
13 views44 pages

Lecture 4 - Stack

This document covers the Stack Abstract Data Type (ADT), including its definition, operations, and implementations using dynamic arrays and linked structures. It discusses various applications of stacks, such as function call management, expression evaluation, and symbol balancing. Additionally, it provides code examples for implementing stack operations and solving problems using stacks in C++.

Uploaded by

Nona Amir
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
You are on page 1/ 44

Data Structures and Algorithms

Stack

1
The Stack ADT
◼Introduction to the Stack data
structure
◼Designing a Stack class using
dynamic arrays
◼Linked Stacks
◼Some Applications of Stacks

2
1. Introduction to the Stack Data Structure
▪ A simple data container consisting of a linear list
of elements
▪ Access is by position (order of insertion)
▪ All insertions and deletions are done at one end,
called top
▪ Last In First Out (LIFO) structure
▪ Two basic operations:
push: add to top
pop: remove from top
3
Example
2. An illustration: A Stack of Plates

Stack Push Stack Pop


of a of a
plates plate plates plate
onto with a from
the new the
stack plate stack
on top

4
Example
push

top ++top top

top top top--


pop

5
Some Stack Applications
◼Run-time stack used in function calls
◼Page-visited history in a Web browser
◼Undo sequence in a text editor
◼Removal of recursion
◼Conversion of Infix to Postfix notation
◼Evaluation of Postfix expressions
◼Reversal of sequences
◼Checking for balanced symbols
6
Stack Class Operations
◼ construct: construct an empty stack
◼ stackIsEmpty → bool : return True if stack
is empty
◼ stackIsFull → bool : return True if stack is
full
◼ push(el) : add element (el) at the top
◼ pop(el): retrieve and remove the top element
◼ stackTop(el): retrieve top element without
removing it
7
2. Array Based Stack Class Definition
◼The stack may be implemented as a
dynamic array.
◼The capacity (MaxSize) will be input as
a parameter to the constructor (default
is 128)
◼The stack ADT will be implemented as a
template class to allow for different
element types.

8
A Stack Class Definition
// File: Stackt.h
// Stack template class definition.
// Dynamic array implementation

#ifndef STACKT_H
#define STACKT_H

template <class Type>

class Stackt
{
public:

Stackt (int nelements = 128); // Constructor


Stackt (const Stackt <Type> &); // Copy Constructor
~Stackt (); // Destructor

9
A Stack Class Definition
// Member Functions
void push(Type ); // Push
void pop(Type &); // Pop
void stackTop(Type &) const; // retrieve top
bool stackIsEmpty() const; // Test for Empty stack
bool stackIsFull() const; // Test for Full stack

private:
Type *stack; // pointer to dynamic array
int top, MaxSize;
};

#endif // STACKT_H
#include "Stackt.cpp"

10
A Stack Implementation
void push(Type &value)
{
if(top== MaxSize -1)
cout<<"Stack is full!\n";
else {
top++;
stack[top]=value;
}
}
void pop() //correct the function
{
if(isempty())
cout<<"Stack is empty!\n";
else
top--;
}
A Stack Class Definition
template <class T> bool Stack<T>::isFull()
{

if (top == (SIZE - 1))


return 1;
else
Return 0;
}
3. Linked Stacks

◼A stack can be implemented as a linked


structure.
◼Requires more space than array
implementations, but more flexible in size.
◼Easy to implement because operations are
at the top (in this case the head node)

13
Node Specification
// The linked structure for a node can be
// specified as a Class in the private part of
// the main stack class.
class node // Hidden from user
{
public:
Type e; // stack element
node *next; // pointer to next node
}; // end of class node declaration

typedef node * NodePointer;

NodePointer top; // pointer to top

14
Push Operation
First Last

top
3 2
New
push(v):
NodePointer pnew = new
node ;
1 pnew->e = v;
pnew
pnew->next = top;
top = pnew;
15
Push Operation
First Last

top
3 2
New
push(v):
NodePointer pnew = new
node ;
1 pnew->e = v;
pnew
pnew->next = top;
top = pnew;
16
Pop Operation
1
cursor
top

2
Type pop():
Type v = top->e;
Nodepointer cursor = top;
top = top->next;
delete cursor;
Return v;
17
Linked Stack Class
// File: StackL.h
// Linked List Stack class definition
#ifndef STACKL_H
#define STACKL_H
template <class Type>
class StackL
{
public:

StackL(); // Constructor
~StackL(); // Destructor
void push(Type ); // Push
void pop(Type &);// Pop

18
Linked Stack Class
void stackTop(Type &) const; // retrieve top
bool stackIsEmpty() const; // Test for Empty stack
private:
// Node Class
class node
{
public:
Type e; // stack element
node *next; // pointer to next node
}; // end of class node declaration

19
Linked Stack Class
typedef node * NodePointer;
NodePointer top; // pointer to top
};
#endif // STACKL_H
#include "StackL.cpp"

20
Linked Stack Class
template <class T> Stack<T>::Stack() { top = -1; }
template <class T> void Stack<T>::push(T k)
{
if (isFull()) {
// Display message when no elements can be pushed
// into it
cout << "Stack is full\n";
}
node<T>* P = new node;
P-> e=k;
P->next = top;
top =P;
}
Linked Stack Class
template <class T> bool Stack<T>::isEmpty()
{
if (top == null)
return 1;
else
return 0;
}
Linked Stack Class
int main()
{
Stack<int> integer_stack;
Stack<string> string_stack;

integer_stack.push(2);
integer_stack.push(54);
integer_stack.push(255);

string_stack.push("Welcome");
string_stack.push("to");
string_stack.push("GeeksforGeeks");

cout << integer_stack.pop() << " is removed from stack"


<< endl;
}
4. Some Applications of Stacks

◼Balancing Enclosure Symbols


◼Evaluation of Postfix Expressions
◼Backtracking
◼Conversion from Decimal to
Hexadecimal (Self study)
◼Converting Infix Expressions to Postfix
(Self study)

24
(b) Balancing Enclosure Symbols
Given a text file containing a sequence of characters, we
want to check for balancing of the symbols ( ) , [ ] , { }.
Algorithm:
bool EnclosureBalance (filename)
{
Open file filename;
Initialize an empty stack of characters;
balanced = true;
for each character (ch) read until end of file :
{
If (ch is a left symbol) push ch on the stack;

25
Balancing Enclosure Symbols
else if (ch is a right symbol) then
if (stack is empty) balanced = false;
else
{
pop the stack;
if (popped symbol is not the corresponding
left symbol) balanced = false;
}
}
At the end of the file,
if (stack is not empty) balanced = false;
return balanced;
}

26
bool areBracketsBalanced(string expr)
{
stack<char> s;
char x;
// Traversing the Expression
for (int i = 0; i < expr.length(); i++)
{
if (expr[i] == '(' || expr[i] == '['
|| expr[i] == '{')
{
// Push the element in the stack
s.push(expr[i]);
continue;
}
if (s.empty())
return false;
switch (expr[i]) {
case ')':
// Store the top element in a
x = s.top();
s.pop();
if (x == '{' || x == '[')
return false;
break;
case '}':
// Store the top element in b
x = s.top();
s.pop();
if (x == '(' || x == '[')
return false;
break;
case ']':
// Store the top element in c
x = s.top();
s.pop();
if (x == '(' || x == '{')
return false;
break;
}
}
// Check Empty Stack
return (s.empty());
}
Main Function
int main()
{
string expr = "{()}[]";

// Function call
if (areBracketsBalanced(expr))
cout << "Balanced";
else
cout << "Not Balanced";
return 0;
}
(c) Evaluation of Postfix Expressions
◼ Regular expressions are written in “infix”
notation, i.e., operator between two operands,
e.g.,
(A+B) * (C- (D+E))
◼ Parentheses are used to force precedence
◼ Reverse Polish Notation (RPN) or “postfix”
does without parentheses. e.g. the above
expression is:
AB+CDE+-*
◼ Postfix expressions like A B + are evaluated as
A+B
31
Evaluation of Postfix Expressions
The idea is:
◼ Scan from left to right until an operator (+,-,*,/)
is encountered.
◼ Apply operator between the previous
operands.
◼ Replace the two previous operands by the
result.

This suggests to use a stack to store operands


and the results.
32
Evaluation of Postfix Expressions (Example)

A B + C D E + - *
R1 C D E + - *
R1 C R2 - *
R1 C R2 - *
R1 R3 *
R1 R3 * = RESULT
33
Evaluation of Postfix Expressions (Example)

(2+3) * (2- (4+1)) → 2 3 + 2 4 1 + - *


2 3 + 2 4 1 + - *
5 2 4 1 + - *
5 2 5 - *
5 2 5 - *
5 -3 *
5 -3 * = RESULT = -15

34
Evaluation of Postfix Expressions (Algorithm)

◼ Initialize a stack (S) of characters


◼ For each character from left to right
◼ Get next character
◼ If operand, push it on S
◼ If an operator:
– Pop two values (error if there are no two values)
– Apply operator
– Push result back onto (S)
◼ At the end, result is on top of (S) (the only
value, otherwise an error)

35
(e) Backtracking (Maze Problem)
◼ A Maze can be modeled as nodes (decision points) and edges
(tracks). A Backtracking method can be used to find the way
tointhe exit starting from an entrance.

A
out F G

B
E

C
D

36
Backtracking (Maze Problem)
◼ We may choose to move in the order:
South – East – North – West
◼ A stack is used to record the tracks.
◼ When we move on a new track, we push it on
the stack.
◼ When we run out of tracks, we backtrack by
popping the last track from the stack.

Later in the course, we will do this using a


recursive algorithm using the system stack.
The algorithm is called Depth First Search
37
Sample Problem
Write a C++ program to reverse a string using a stack.
string reverseString(const std::string& input) {
std::stack<char> stack;
// Push all characters of the string onto the stack
for (char ch : input) {
stack.push(ch);
}

while (!stack.empty()) {
reversed += stack.top();
stack.pop();
}

return reversed;
}
int main() {
string input;
cout << "Enter a string to reverse: ";
getline(cin, input);

string reversed = reverseString(input);


cout << "Reversed string: " << reversed << endl;

return 0;
}
Sample Problem
Q-Given an of N integers array, print the Next Greater
Element (NGE) for every element.
• Please use the appropriate data structure that helps you to
minimize the code

Input: arr[] = [ 13 , 7, 6 , 12 ]
Output: 13 –> -1
7 –> 12
6 –> 12
12 –> -1
Explanation: 13 and 12 don’t have any element greater than them
present on the right side
void printNGE(int arr[], int n)
{
stack<int> s;
/* push the first element to stack */
s.push(arr[0]);
// iterate for rest of the elements
for (int i = 1; i < n; i++)
{
if (s.empty()) {
s.push(arr[i]);
continue;
}
/* if stack is not empty, then
pop an element from stack.
If the popped element is smaller
than next, then
a) print the pair
b) keep popping while elements are
smaller and stack is not empty */
while (s.empty() == false && s.top() < arr[i]) {
cout << s.top() << " --> " << arr[i] << endl;
s.pop();
}

/* push next to stack so that we can find


next greater for it */
s.push(arr[i]);
}
/* After iterating over the loop, the remaining
elements in stack do not have the next greater
element, so print -1 for them */
while (s.empty() == false) {
cout << s.top() << " --> " << -1 << endl;
s.pop();
}
}

/* Driver code */
int main()
{
int arr[] = { 11, 13, 21, 3 };
int n = sizeof(arr) / sizeof(arr[0]);
printNGE(arr, n);
return 0;
}

You might also like