You are on page 1of 73

Linear Data Structure:

Stack

Dr. Jyoti Srivastava


What is a stack?
(Basic features of Stack)
• A stack is an Abstract Data Type (ADT) that contains an ordered
group of homogeneous elements.
• The last element to be added is the first to be removed (LIFO: Last
In, First Out).
• push() function is used to insert new elements into the Stack.
• pop() is used to delete an element from the stack.
• Both insertion and deletion are allowed at only one end of Stack
called Top.
• Stack is said to be in Overflow state when it is completely full.
• Stack is said to be in Underflow state if it is completely empty.
Basic Stack Operations
• Initialize(): Initialize the Stack.

• isFull() : Is the Stack full?

• Push(): insert an item onto the top of the


stack

• isEmpty(): Is the Stack empty?

• POP(): delete an item from top of the stack.

• peep(): get the top data element of the stack,


without removing it.
Stack (Size = N)

Position of Top Status of Stack


-1 Stack is Empty
0 Only one element in Stack
N-1 Stack is Full
N Overflow state of Stack
Implementation of Stack
• Stack can be easily implemented using an Array or a
Linked List.

• Arrays are quick, but are limited in size.

• Linked List requires overhead to allocate, link,


unlink, and deallocate, but is not limited in size.
Array Implementation of the Stacks

•The stacks can be implemented by the use of


arrays.

• One way to implement the stack is to have a data


structure where a variable called top keeps the
location of the elements in the stack (array)

• An array is used to store the elements in the stack


Stack Definition

struct STACK{
int count;// keeps the number of elements in the stack
int top;// indicates the location of the top of the stack
int items[STACKSIZE];//array to store the stack
elements
}
Stacks
Push Operation
• Push an item onto the top of the stack (insert an item)
push()

•Function: Adds new Item to the top of the


stack.

•Preconditions: Stack has been initialized and


is not full.

•Postconditions: new Item is at the top of the


stack.
Push(S,TOP,X)
This procedure inserts an element X to the top of a stack which is
represented by a vector S containing N elements with a pointer TOP
denoting the top element of the stack.
1. [check for stack overflow]
if TOP =N-1
then Write(“stack overflow”)
Return
2. [increment Top]
TOP = TOP+1
3. [insert element]
S[TOP] = X
4. [finished]
Return
The first step of this algorithm checks for overflow condition. If such a
condition exists then the insertion operation cannot be performed .
Pop operation
Pop an item from the top of the stack (delete an item)
pop()
• Function: Removes top Item from stack and returns
with top Item

• Preconditions: Stack has been initialized and is not


empty.

• Postconditions: Top element has been removed from


stack and the function returns with the top element.
Pop(S,TOP)
This function removes the top element from the stack which is represented by
the vector S and returns this element. TOP is a pointer to the top of the stack.
1. [check for underflow of the stack]
if TOP=-1
then Write(“stack underflow on pop)
Exit
2. [return former top element of the stack]
X = S[TOP]
3. [decrement pointer]
TOP = TOP-1
4. [finished]
Return X
An underflow condition is checked in the first step. If there is an underflow
then POP actions can not be performed.
peep()
This operation is to read the value on the top of the
stack without removing it.

Algorithm
1. [check for underflow of the stack]
if TOP=-1
then Write(“stack underflow on peep)
Exit
2. [return former top element of the stack]
Return(S[TOP])
EXAMPLE

• The following program implements stack of size 10 using


array representation.

• The 10 elements entered by the user are pushed into the stack
and then the elements are popped back and displayed.
Stack Implementation using Arrays
#include<stdio.h>
#include<stdlib.h>
#define STACKSIZE 10

struct STACK{
int count;
int top;
int items[STACKSIZE]; /*stack can contain up to 10 integers*/
};

void initstack(struct STACK *);


void push(struct STACK *, int);
int pop(struct STACK *);
Inside Main()
int main()
{
int p, i;
struct STACK s;

/* Initialize the stack */


initstack(&s);

/*reading and pushing items into the stack*/


printf("Enter the %d stack items\n",STACKSIZE);
for(i=0;i<= STACKSIZE-1;i++){
scanf("%d", &p);
push(&s, p);
}
/*popping and printing the items in the stack*/

printf("\n\nStack contains the following items\n");


for(i=0;i<= STACKSIZE-1;i++){
p=pop(&s);
printf("%d\t",p);
}
return 0;
}
Initialize
void initstack(struct STACK *s) /* Initialize the Stack*/
{
s->top = -1; /*indicates that the stack is empty at the
beginning*/
s->count = 0; /* 0 items are in the stack*/
printf("Stack is initialized..");
}
Push
void push(struct STACK *Sptr, int ps) /*pushes ps into stack*/
{
if(Sptr->top == STACKSIZE-1){
printf("Stack is full\n");
printf("There are %d items in the stack\n", Sptr->count);
return; /*return back to main function*/
}
else {
Sptr->top++;
Sptr->items[Sptr->top]= ps;
Sptr->count++;
}
}
Pop
int pop(struct STACK *Sptr)
{
int pp;
if(Sptr->top == -1){
printf("Stack is empty\n");
return -1; /*exit from the function*/
}
else {
pp = Sptr->items[Sptr->top];
Sptr->top--;
Sptr->count--;
return pp;
}
}
Stack Implementation using Array
versus Linked List

• Stack Implementation using Array:


• Major problem: it works only for fixed number of data values.
• So the amount of data must be specified at the beginning of the
implementation itself.
• It is not suitable, when we don't know the size of data which we
are going to use.

• Stack Implementation using Linked List:


• The stack implemented using linked list can work for unlimited
number of values.
• So, there is no need to fix the size at the beginning of the
implementation.
Linked Implementation of Stack

• That means every newly inserted element is pointed by


'top’.

• Whenever we want to remove an element from the


stack,
top = top->next

• The next field of the first element must be


always NULL.

• Example: last inserted node is 99 and the first inserted


node is 25. So top points to 99 and next field of 25 is
NULL.
Linked Implementation of Stack

struct Node {
int data;
struct Node *next;
}*top = NULL;
push(value) - Inserting an element into the Stack

Step 1: Create a newNode with given value.

Step 2: Check whether stack


is Empty (top == NULL)

Step 3: If it is Empty, then set


newNode → next = NULL

Step 4: If it is Not Empty, then set


newNode → next = top

Step 5: Finally, set top = newNode


pop() - Deleting an Element from Stack

Step 1: Check whether stack


is Empty (top == NULL).

Step 2: If it is Empty, then


display "Stack is Empty!!!
exit

Step 3: If it is Not Empty, then


define a Node pointer 'temp' and set it to 'top’.

Step 4: Then set 'top = top → next’.

Step 7: Finally, delete 'temp' (free(temp)).


display() - Displaying elements of stack

Step 1: Check whether stack


is Empty (top == NULL).

Step 2: If it is Empty, then


display 'Stack is Empty!!!’
exit.

Step 3: If it is Not Empty, then


define a Node pointer 'temp' and initialize with top.
(temp = top)

Step 4: while temp != NULL


Display 'temp → data ’
temp = temp → next
Applications of Stack
• Stacks can be used for Conversion from one form of
expression to another.

• Stacks can be used for expression evaluation.

• Stacks can be used to check parenthesis matching in an


expression.

• Stacks can be used for Memory Management.

• Stack data structures are used in backtracking problems.


Real life examples of stack are:
• To reverse a word. You push a given word to stack - letter by letter
- and then pop letters from the stack.

• An "undo" mechanism in text editors; this operation is


accomplished by keeping all text changes in a stack.
• Undo/Redo stacks in Excel or Word.

• Language processing :
• space for parameters and local variables is created internally using a stack.
• compiler's syntax check for matching braces is implemented by using stack.

• A stack of plates/books in a cupboard.


• Wearing/Removing Bangles.
• Support for recursion
• Activation records of method calls.
Expression Parsing
• The way to write arithmetic expression is known as
a notation.

• An arithmetic expression can be written in three different


but equivalent notations, i.e., without changing the essence
or output of an expression.

• These notations are −


• Infix Notation
• Prefix (Polish) Notation
• Postfix (Reverse-Polish) Notation

• Stacks are primarily used to convert an expression from


one form to another.
Infix notation

• Within Infix notation, operator is used between two


operands.
Example, A + B

• For humans it is easy to write and understand.

• Computer works efficiently with prefix and postfix.

• Information is needed about operator precedence,


associativity rules and brackets which overrides
these rules.
Prefix Notation
•In this notation, operator is prefixed to
operands, i.e. operator is written ahead of
operands.

•For example, +ab. This is equivalent to its


infix notation a + b.

•Prefix notation is also known as Polish


Notation.
Postfix Notation
• This notation style is known as Reversed Polish
Notation.

• In this notation style, the operator is postfixed to the


operands i.e., the operator is written after the
operands.

• For example, ab+. This is equivalent to its infix


notation a + b.
Parsing Expressions
• it is not a very efficient way to design an
algorithm or program to parse infix notations.

• Instead, these infix notations are first converted


into either postfix or prefix notations and then
computed.

• To parse any arithmetic expression, we need to


take care of operator precedence and
associativity.
Precedence
When an operand is in between two different operators
 which operator will take the operand first, is
decided by the precedence of an operator over
others.
 For example −

As multiplication operation has precedence over


addition, b * c will be evaluated first.
Associativity
• Associativity describes the rule where operators with the
same precedence appear in an expression.

• For example, in expression a + b − c, both + and – have


the same precedence,

• then which part of the expression will be evaluated first


• Here, both + and − are left associative, so the expression
will be evaluated as (a + b) − c.

Example: 8/4*2
will give different results if we perform division first and
then multiplication or vice versa.
Precedence and Associativity

• Precedence and associativity determines the order of


evaluation of an expression.
• Following is an operator precedence and associativity table
(highest to lowest) −
Sr. Operator Precedence Associativity
No.
1 Exponentiation ^ Highest Right
Associative
2 Multiplication ( ∗ ) & Division ( / ) Second Left
Highest Associative
3 Addition ( + ) & Subtraction ( − ) Lowest Left
Associative
Precedence and Associativity
• At any point of time in expression evaluation,

• the order can be altered by using parenthesis.

• For example −

• In a + b*c, the expression part b*c will be evaluated first,


with multiplication has precedence over addition.

• We here use parenthesis for a + b to be evaluated first,


like (a + b)*c.
Postfix notation
• As the name suggests, operator is always placed after operands.
Example:
Infix: A + B
Postfix: AB+
Example:
Infix: (A + B) * C
Postfix: (AB+)C*
AB+C*
Postfix notation
1. (A - B) * (C + D)
[AB -] * [CD +]
AB – CD + *

2. (A + B) / (C + D) – (D * E)
[AB +] / [CD+] – [DE *]
[AB + CD + /] – [DE *]
AB + CD + / DE * -
Postfix notation
•In postfix notation, operators are applied to
the operands that are immediately left to
them.

•AB+C*, + is applied on A and B, then * is


applied on the result of addition and C.
Prefix notation
• In prefix notation, operators are applied to the
operands that are immediately right to them.

• Prefix expressions do not follow rules of operator


precedence and associativity and even brackets can’t
alter the order of evaluation.

(A + B) * C
[+ AB] * C
* + ABC
Prefix notation
1. (A - B) * (C + D)
[- AB] * [+ CD]
* - AB + CD

2. (A + B) / (C + D) – (D * E)
[+ AB] / [+ CD] – [* DE]
[/ + AB + CD] – [* DE]
- / + AB + CD * DE
Infix to Postfix using Stack - Rules
1. Scan from left to right, we shall get a symbol which may be
operator or operand or parenthesis. Follow below steps.
i. If operand, add it to the postfix
ii. If opening parenthesis, push into stack
iii. If operator, then check the top of the stack
a) If stack is empty, push into stack
b) If top is opening parenthesis, push into stack
c) If precedence of operator at top is higher or same as the
current, then repeatedly it is popped and added to postfix
exp, otherwise pushed onto stack
iv. If symbol is closing parenthesis, then
a) repeatedly pop from stack and add each operator to
postfix exp until corresponding parenthesis encountered.
b) Remove opening parenthesis from the stack.
2. If Stack is not empty then pop each symbol and add it to the
postfix.
Example
Convert infix to postfix.
5*(6+2)-(12/4)
5*[62+]-[124/]
562+*-124/
562+*124/-
5*(6+2)-(12/4)
Symbol Scanned Stack Postfix Exp
1 5 5
2 * * 5
3 ( *, ( 5
4 6 *, ( 5, 6
5 + *, (, + 5, 6
6 2 *, (, + 5, 6, 2
7 ) * 5, 6, 2, +
8 - - 5, 6, 2, +, *
9 ( -,( 5, 6, 2, +, *
10 12 -,( 5, 6, 2, +, *, 12
11 / - , (, / 5, 6, 2, +, *, 12
12 4 - , (, / 5, 6, 2, +, *, 12, 4
13 ) - 5, 6, 2, +, *, 12, 4, /
14 5, 6, 2, +, *, 12, 4, /, -
Scanned Char Stack Postfix Exp
a+b*c-d/e*h
a a
+ + a
b + ab
* +,* ab
c +,* abc
- - abc*+
d - abc*+d
/ -,/ abc*+d
e -,/ abc*+de
* -,* abc*+de/
h -,* abc*+de/h
- abc*+de/h*
abc*+de/h*-
Practice

1. (a+((b*c)*d))
2. a/b^c-d
3. (a-b/c)*(d*e-f)
Infix to Prefix

A/B^C-D

A/^BC-D

/A^BC-D

-/A^BCD
Infix to Prefix using Stack - Rules
1. Scan from right to left or reverse the string.
I. If operand add to o/p string
II. If it is closing parenthesis, push on stack
III. If an operator, then
a) If stack is empty, push into stack
b) If top is closing parenthesis, push into stack
c) If precedence of operator at top is higher, pop from stack and
add to the o/p string Else push operator
IV. If symbol is opening parenthesis, then
a) pop operators from stack and add to o/p string until
corresponding closing parenthesis encountered.
b) Remove parenthesis from the stack.
2. If Stack is not empty then pop each symbol and add it to the o/p
string.
3. Reverse the output string.
A/B^C-D
Char Scanned Stack Prefix Exp
D D
- - D
C - DC
^ -^ DC
B -^ DCB
/ -/ DCB^
A -/ DCB^A
- DCB^A/
DCB^A/-
Reverse it
-/A^BCD
Practice
1. (A-B/C)*(D*E-F)
2. (A+((B*B)*D))
Evaluation of postfix using Stack
1. Scan from left to right
2. If operand is encountered push it into stack
3. If an operator ‘$’ is found,
1. Pop two elements from stack where B is the top
element and A is next top element
2. Evaluate A $ B
3. Push the result on stack
4. Repeat step 1 to 3.
5. Evaluated value is equal to the value at top of
stack
Example#1
• Postfix String : 123*+4-
• Initially the Stack is empty. Now, the first three
characters scanned are 1,2 and 3, which are
operands. Thus they will be pushed into the stack in
that order.
Example#1
• Next character scanned is "*", which is an operator.
Thus, we pop the top two elements from the stack
and perform the "*" operation with the two
operands. The second operand will be the first
element that is popped.
Example#1
• The value of the expression(2*3) that has been evaluated(6) is
pushed into the stack.

• Next character scanned is "+", which is an operator. Thus, we


pop the top two elements from the stack and perform the "+"
operation with the two operands. The second operand will be
the first element that is popped.
Example#1

• The value of the expression(1+6) that has been


evaluated(7) is pushed into the stack.

• Next character scanned is "4", which is added to the


stack.
Example#1
• Next character scanned is "-", which is an operator. Thus, we
pop the top two elements from the stack and perform the "-"
operation with the two operands. The second operand will be
the first element that is popped.

• The value of the expression(7-4) that has been evaluated(3) is


pushed into the stack.
Example#1
• Now, since all the characters are scanned, the
remaining element in the stack (there will be only
one element in the stack) will be returned.

End result :
• Postfix String : 123*+4-
• Result : 3
5, 6, 2, +, *, 12, 4, /, -
Scanned Symbol Stack Operation
5 5
6 5, 6
2 5, 6, 2
+ 5, 8 6 + 2 (A=6, B=2)
* 40 5 * 8 (A=5, B=8)
12 40, 12
4 40, 12, 4
/ 40, 3 12 / 4 (A=12, B=4)
- 37 40 – 3(A=40, B=3)
Practice

1. 5 9 8 + 4 6 * + 7 - *
2. 7, 2, -, 1, 3, +, /
Tower of Hanoi
• Recursive application

• It says, “If you can solve n-1 cases, then you can easily
solve nth case”
Tower of Hanoi
• In problem,
• there are three posts.
• Disks of different sizes (call the number of disks "n") are placed
on the lefthand post, arranged by size with the smallest on top.
• You have to transfer all the disks to the right hand post in the
fewest possible moves, without ever placing a larger disk on a
smaller one.
• One move is considered to be moving one disk from one post to
another post.
Tower of Hanoi
Tower of Hanoi - Recursive

1. Move the top N - 1 disks from Src to Spare(using


Dst as an intermediary peg)
2. Move the bottom disk from Src to Dst
3. Move N - 1 disks from Spare to Dst (using Src as
an intermediary peg)
move(int n, char src, char dst, char spare)
if (n==1)
printf(“Move from % c to % c”,src, dst);
else
move(n-1, src, spare, dst) ;
move(1, src, dst, spare);
move(n-1, spare, dst, src);
Tower of Hanoi - Recursive
move(int n, char src, char dst, char spare)
if (n==1)
printf(“Move from % c to % c”,src, dst);
else
move(n-1, src, spare, dst) ;
move(1, src, dst, spare);
move(n-1, spare, dst, src);

• If n=2, means source (a) is having 2 disks to be


transferred over destination (c), using spare (b)
move(2, a, c, b) ;
move(1, a, b, c) ; [a->b]
move(1, a, c, b); [a->c]
move(1, b, c, a); [b->c]
Tower of Hanoi - Recursive

• If n=3, means source (a) is having 3 disks to be


transferred over destination (c), using spare (b)
N=3
move(n-1, src, spare, dst) ;
Src a
move(1, src, dst, spare);
move(n-1, spare, dst, src); Dst c
Spr b

move(2, a, b, c) ; here n=2, so recursion will take place


move(1, a, c, b); here n=1, so move is possible [a->c]
move(2, b, c, a); here n=2, so recursion will take place
Tower of Hanoi - Recursive

Step1: move(2, a, b, c) ; here n=2, so recursion will take


place
move(1, a, c, b) ; here n=1, so move is possible [a->c]
move(1, a, b, c) ; here n=1, so move is possible [a->b]
move(1, c, b, a) ; here n=1, so move is possible [c->b]

N=3 N = 2 in Step 1
Src a a move(n-1, src, spare, dst) ;
Dst c b move(1, src, dst, spare);
Spr b c
move(n-1, spare, dst, src);
Tower of Hanoi - Recursive
Step2: move(1, a, c, b); here n=1, so move is possible [a->c]
Step3: move(2, b, c, a); here n=2, so recursion will take
place
move(1, b, a, c) ; here n=1, so move is possible [b->a]
move(1, b, c, a) ; here n=1, so move is possible [b->c]
move(1, a, c, b) ; here n=1, so move is possible [a->c]

move(n-1, src, spare, dst) ;


move(1, src, dst, spare);
move(n-1, spare, dst, src);
N=3 N = 2 in Step 1 N = 2 in Step 3
Src a a b
Dst c b c
Spr b c a
Tower of Hanoi - Recursive
Solution, when n=3
[a->c]
[a->b]
[c->b]
[a->c]
[b->a]
[b->c]
[a->c]
Tower of Hanoi Pattern
• Number of Disks Number of Moves
1 1
2 3
3 7
4 15
5 31

• Powers of two help reveal the pattern:


• Number of Disks (n) Number of Moves
1 2^1 - 1 = 2 - 1 = 1
2 2^2 - 1 = 4 - 1 = 3
3 2^3 - 1 = 8 - 1 = 7
4 2^4 - 1 = 16 - 1 = 15
5 2^5 - 1 = 32 - 1 = 31
Tower of Hanoi Animation

1. http://britton.disted.camosun.bc.ca/hanoi.swf

2. https://www.youtube.com/watch?v=5_6nsViVM00

You might also like