Lecture 4 - Stack
Lecture 4 - Stack
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
4
Example
push
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
class Stackt
{
public:
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()
{
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
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");
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.
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)
34
Evaluation of Postfix Expressions (Algorithm)
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.
while (!stack.empty()) {
reversed += stack.top();
stack.pop();
}
return reversed;
}
int main() {
string input;
cout << "Enter a string to reverse: ";
getline(cin, input);
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();
}
/* Driver code */
int main()
{
int arr[] = { 11, 13, 21, 3 };
int n = sizeof(arr) / sizeof(arr[0]);
printNGE(arr, n);
return 0;
}