0% found this document useful (0 votes)
8 views

DS Stack Queue

Uploaded by

Vipul Kamboj
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

DS Stack Queue

Uploaded by

Vipul Kamboj
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 96

Data Structures with C

(Stack and Queues)


Lecture
Stack

2 2022
Today’s discussion…

*Stack
* Basic principles
* Operation of stack
* Stack using Array
* Stack using Linked List
* Applications of stack

3
Stack

4
Basic Idea
•A stack is an Abstract Data Type (ADT), commonly used in most
programming languages. It is named stack as it behaves like a real-
world stack, for example – a deck of cards or a pile of plates, etc.

5
Stack Representation

• Can be implemented by means of Array, Structure, Pointers and


Linked List.
• Stack can either be a fixed size or dynamic.
6
push
STACK
pop

create

isempty

isfull

7
STACK: Last-In-First-Out (LIFO)
• void push (stack *s, int element);
/* Insert an element in the stack */
• int pop (stack *s);
/* Remove and return the top element */
• void create (stack *s);
/* Create a new stack */
• int isempty (stack *s);
/* Check if stack is empty */
• int isfull (stack *s);
/* Check if stack is full */

Assumption: stack contains integer elements!


8
Stack using Array

9
Push using Stack

PUSH

top
top

10
Pop using Stack

POP

top
top DEMO

11
DEMO

*DEMO
12
Stack using Linked List

13
Push using Linked List

PUSH OPERATION

top

14
Pop using Linked List

POP OPERATION

top

Linked Lis
t based St
ack
Demo

15
Basic Idea
• In the array implementation, we would:
• Declare an array of fixed size (which determines the maximum size of
the stack).

• Keep a variable which always points to the “top” of the stack.


• Contains the array index of the “top” element.
• In the linked list implementation, we would:
• Maintain the stack as a linked list.
• A pointer variable top points to the start of the list.
• The first element of the linked list is considered as the stack top.
16
Declaration

#define MAXSIZE 100 struct lifo


{
struct lifo int value;
{ struct lifo *next;
int st[MAXSIZE]; };
int top; typedef struct lifo stack;
};
typedef struct lifo stack; stack *top;
stack s;

ARRAY LINKED LIST

17
Stack Creation

void create (stack *s) void create (stack **top)


{ {
s->top = -1; *top = NULL;
/* s->top points to /* top points to NULL,
last element indicating empty
pushed in; stack */
initially -1 */ }
}

ARRAY LINKED LIST

18
Pushing an element into stack

void push (stack *s, int element) void push (stack **top, int element)
{ {
stack *new;
if (s->top == (MAXSIZE-1))
{ new = (stack *)malloc (sizeof(stack));
printf (“\n Stack overflow”); if (new == NULL)
exit(-1); {
} printf (“\n Stack is full”);
else exit(-1);
}
{
s->top++; new->value = element;
s->st[s->top] = element; new->next = *top;
} *top = new;
} }

ARRAY LINKED LIST


19
Popping an element from stack
int pop (stack **top)
int pop (stack *s) {
int t;
{ stack *p;
if (s->top == -1) if (*top == NULL)
{ {
printf (“\n Stack underflow”); printf (“\n Stack is empty”);
exit(-1);
exit(-1); }
} else
else {
t = (*top)->value;
{ p = *top;
return (s->st[s->top--]); *top = (*top)->next;
free (p);
} return t;
} }
}

ARRAY LINKED LIST


20
Checking for stack empty

int isempty (stack *s) int isempty (stack *top)


{ {
if (s->top == -1) if (top == NULL)
return 1; return (1);
else else
return (0); return (0);
} }

ARRAY LINKED LIST

21
Checking for Stack Full

int isfull (stack *s) int isfull (stack *top)


{ {
if (s->top == MAXSIZE-1) if (top == NULL)
return 1; return (1);
else else
return (0); return (0);
} }

ARRAY LINKED LIST

22
30
Example: A Stack using an Array
#include <stdio.h>
#define MAXSIZE 100 20
struct lifo 5
{
int st[MAXSIZE]; 10 100
int top;
};
typedef struct lifo stack;
main() {
stack A, B;
create(&A);
create(&B);
push(&A,10);
push(&A,20);
push(&A,30);
push(&B,100);
push(&B,5);
printf (“%d %d”, pop(&A), pop(&B));
push (&A, pop(&B));
if (isempty(&B))
printf (“\n B is empty”);
23
return;
}
Example: A Stack using Linked List
#include <stdio.h>
struct lifo
{
int value;
struct lifo *next;
};
typedef struct lifo stack;
main() {
stack *A, *B;
create(&A);
create(&B);
push(&A,10);
push(&A,20);
push(&A,30);
push(&B,100);
push(&B,5);
printf (“%d %d”, pop(&A), pop(&B));
push (&A, pop(&B));
if (isempty(B))
printf (“\n B is empty”);
return; 24
}
Applications of Stacks
• Direct applications:
• Page-visited history in a Web browser
• Undo sequence in a text editor
• Chain of method calls in the Java Virtual Machine
• Validate XML

• Indirect applications:
• Auxiliary data structure for algorithms
• Component of other data structures

25
*Example of Stack operations
26
* Infix and Postfix
An application of Stack

27
*Infix Notation
*To add A, B, we write A+B
*To multiply A, B, we write A*B
* The operators ('+' and '*') go in between the operands ('A'
and 'B') This is "Infix" notation

28
Operator Priority Associativity
^ High Right to left
*, / Medium Left to right
+, - Low Left to right

*Precedence and Associativity


of operators
29
* Instead of saying "A plus B", we could say "add A,B
" and write + A B
* "Multiply A,B" would be written * A B
* This is Prefix notation

*Prefix Notation.
30
* Another alternative is to put the operators after the operands as in
AB+
and
AB*
* This is Postfix notation.
* The terms infix, prefix, and postfix tell us whether the operators go
between, before, or after the operands

*Postfix Notation
31
* Evaluate 2+3*5.
* + First:
(2+3)*5 = 5*5 = 25
* * First:
2+(3*5) = 2+15 = 17
* Infix notation requires Parentheses.

*Parentheses
32
*• + 2 * 3 5 =
* =+2*35
* = + 2 15 = 17
*• * + 2 3 5 =
* =*+235
* = * 5 5 = 25

* • No parentheses needed!!

*What about Prefix Notation?


33
*2 3 5 * + =
* =235*+
* = 2 15 + = 17
*23+5*=
* =23+5*
* = 5 5 * = 25
* No parentheses needed here either

*Postfix Notation •
34
Infix and Postfix Notations
• Infix: operators placed between operands:
A+B*C
• Postfix: operands appear before their operators:-
ABC*+
• There are no precedence rules to learn in postfix notation, and
parentheses are never needed

35
Infix to Postfix
Infix Postfix
A+B AB+
A+B*C ABC*+
(A + B) * C AB+C*
A+B*C+D ABC*+D+
(A + B) * (C + D) AB+CD+*
A*B+C*D AB*CD*+

A+B* C  (A + (B * C))  (A + (B C *) )  A B C * +

A + B * C + D  ((A + (B * C)) + D )  ((A + (B C*) )+ D) 


((A B C *+) + D)  A B C * + D +
36
* Parenthesis Method
* Step 1: Fully parenthesize the expression
* Step 2: Replace right parenthesis (closing parenthesis) by moving operator over it.
* Delete left parenthesis (opening parenthesis).
* eg. Given Expression - A+B*C/D^E-F;
* Fully parenthesize – ((A+((B*C)/(D^E)))-F);
* Moving operators to their right parenthesis - ( ( A ( ( B C * ( D E ^ / + F -;
* Delete all left parenthesis – A B C * D E ^ / + F -;
* Note: It requires multiple traversals of the expression.

*Infix to Postfix conversion


37
Infix to postfix conversion
• Use a stack for processing operators (push and pop operations).
• Scan the sequence of operators and operands from left to right
and perform one of the following:
• output the operand,
• push an operator of higher precedence,
• pop an operator and output, till the stack top contains
operator of a lower precedence and push the present operator.

38
The algorithm steps
1. Print operands as they arrive.
2. If the stack is empty or contains a left parenthesis “(“ on top, push the incoming operator onto the
stack.
3. If the incoming symbol is a left parenthesis “(“, push it on the stack.
4. If the incoming symbol is a right parenthesis “)”, pop the stack and print the operators until you see a
left parenthesis. Discard the pair of parentheses.
5. If the incoming symbol has higher precedence than the top of the stack, push it on the stack.
6. If the incoming symbol has equal precedence with the top of the stack, use association. If the
association is left to right, pop and print the top of the stack and then push the incoming operator. If
the association is right to left, push the incoming operator.
7. If the incoming symbol has lower precedence than the symbol on the top of the stack, pop the stack
and print the top operator. Then test the incoming operator against the new top of stack.
8. At the end of the expression, pop and print all operators on the stack. (No parentheses should remain.)
39
Infix to Postfix Conversion
Requires operator precedence information

Operands:
Add to postfix expression.

Close parenthesis:
pop stack symbols until an open parenthesis appears.

Operators:
Pop all stack symbols until a symbol of lower precedence appears. Then push the
operator.

End of input:
Pop all remaining stack symbols and add to the expression.
40
stack s
char ch, element *Infix to Postfix Rules
while(tokens are available) {
ch = read(token);
if(ch is operand) {
print ch ;
} else {
while(priority(ch) <= priority(top most stack)) {
element = pop(s);
print(element);
}
push(s,ch);
}
}
while(!empty(s)) {
element = pop(s);
print(element);
}

41
stack

infixVect
(a+b-c)*d–(e+f)

postfixVect
stack

infixVect
a+b-c)*d–(e+f)

postfixVect

(
Stack

infixVect
+b-c)*d–(e+f)

postfixVect
a

(
Stack

infixVect
b-c)*d–(e+f)

postfixVect
a

+
(
Stack

infixVect
-c)*d–(e+f)

postfixVect
ab

+
(
Stack

infixVect
c)*d–(e+f)

postfixVect
ab+
-
(
Stack

infixVect
)*d–(e+f)

postfixVect
ab+c

-
(
Stack

infixVect
*d–(e+f)

postfixVect
ab+c-
Stack

infixVect
d–(e+f)

postfixVect
ab+c-

*
Stack

infixVect
–(e+f)

postfixVect
ab+c-d

*
Stack

infixVect
(e+f)

postfixVect
ab+c–d*

-
Stack

infixVect
e+f)

postfixVect
ab+c–d*

(
-
Stack

infixVect
+f)

postfixVect
ab+c–d*e

(
-
Stack

infixVect
f)

postfixVect
ab+c–d*e
+
(
-
Stack

infixVect
)

postfixVect
ab+c–d*ef
+
(
-
Stack

infixVect

postfixVect
ab+c–d*ef+

-
Stack

infixVect

postfixVect
ab+c–d*ef+-
* Char Stack[1:n]; / Stack to hold operators Int top =
0; / stack is initially empty String E; / E is string which
contains input infix expression Infix_To_Postfix(E)
Case: x is an operator
{
while ( ISP( stack[top] ) > = ICP( x ) )
For( i = 1 to Length (E)) {
{ x = E[i]; / Get the next symbol print : Stack[ top ];
Case : x is an operand top = top - 1 ;
Print : X; continue; }
Case : x = = ‘;’ top = top + 1;
stack [ top ] = x;
while(top>0)
}
{ print: stack[top];
}
top = top – 1; }
print: ‘;’ ; return;
Case : x = = ‘)’
while ( stack[top] ! = ‘(‘ )
{
print: stack[top];
top = top - 1; }
top = top – 1;
continue; 59
Infix to Postfix Rules
Current Operator Postfix string
Expression: symbol Stack
1 A A
A * (B + C * D) + E
2 * * A

becomes 3 ( *( A
4 B *( AB
ABC D * +* E+ 5 + *(+ AB
6 C *(+ ABC
7 * *(+* ABC
8 D *(+* ABCD
Postfix notation
is also called as 9 ) * ABCD*+
Reverse Polish 10 + + ABCD*+*
Notation (RPN) 11 E + ABCD*+*E
12 ABCD*+*E+
60
Infix to postfix
* A * (B + C * D) + E

* current Symbol Operator Stack Postfix String


* 1 A A
* 2 * * A
* 3. ( *( A
* 4 B *( AB
* 5 + *(+ AB
* 6 C *(+ ABC
* 7 * *(+* ABC
* 8 D *(+* ABCD
* 9 ) * ABCD*
* ABCD*+
* ABCD*+*
* 10 + + ABCD*+*
* 11 E + ABCD*+*E
* 12 ABCD*+*E+

61
Algorithm to convert Infix To Postfix
* Let, X is an arithmetic expression written in infix notation. This algorithm finds the equivalent postfix
expression Y.
* Push “(“onto Stack, and add “)” to the end of X.
* Scan X from left to right and repeat Step 3 to 6 for each element of X until the Stack is empty.
* If an operand is encountered, add it to Y.
* If a left parenthesis is encountered, push it onto Stack.
* If an operator is encountered ,then:
* Repeatedly pop from Stack and add to Y each operator (on the top of Stack) which has the same precedence as or
higher precedence than operator.
* Add operator to Stack.
[End of If]
* If a right parenthesis is encountered ,then:
* Repeatedly pop from Stack and add to Y each operator (on the top of Stack) until a left parenthesis is encountered.
* Remove the left Parenthesis.
[End of If]
[End of If]
* END. 62
Infix Expression:
A+ (B*C-(D/E^F)*G)*H,
where ^ is an exponential operator.

63
int precedence(char symbol)
{
if(symbol == '^')/* exponent operator, highest precedence*/
{ return(3); }
else if(symbol == '*' || symbol == '/')
{ return(2); }
else if(symbol == '+' || symbol == '-') /* lowest precedence */
{ return(1); }
else
{ return(0); }
}

64
*Infix to prefix
Input : A * B + C / D
Output : + * A B/ C D

Input : (A - B/C) * (A/K-L)

Output : *-A/BC-/AKL
65
Infix to Prefix
* Step 1: Reverse the infix expression i.e A+B*C will
become C*B+A.
* Note while reversing each ‘(‘ will become ‘)’ and each ‘)’
becomes ‘(‘.
* Step 2: Obtain the “nearly” postfix expression of the
modified expression i.e CB*A+.
* Step 3: Reverse the postfix expression. Hence in our
example prefix is +A*BC.

66
Step 1. Push “)” onto STACK, and add “(“ to end of the A
Step 2. Scan A from right to left and repeat step 3 to 6 for each element of A until the STACK is empty
Step 3. If an operand is encountered add it to B
Step 4. If a right parenthesis is encountered push it onto STACK
Step 5. If an operator is encountered then:
a. Repeatedly pop from STACK and add to B each operator (on the top of STACK) which has same
or higher precedence than the operator.
b. Add operator to STACK
Step 6. If left parenthesis is encontered then
a. Repeatedly pop from the STACK and add to B (each operator on top of stack until a left
parenthesis is encounterd)
b. Remove the left parenthesis
Step 7. Exit

Infix to prefix algorithm


67
Expression = (A+B^C)*D+E^5 Expression Stack Output Comment
Step 1. Reverse the infix expression. 5^E+D*(C^B+A) Empty - Initial
5^E+D*)C^B+A( ^E+D*(C^B+A) Empty 5 Print
Step 2. Make Every '(' as ')' and every ')' as
E+D*(C^B+A) ^ 5 Push
'(' +D*(C^B+A) ^ 5E Push
D*(C^B+A) + 5E^ Pop And Push
5^E+D*(C^B+A)
*(C^B+A)+ 5E^D Print
Step 3. Convert expression to postfix
(C^B+A) +* 5E^D Push
form.
C^B+A) +*( 5E^D Push
A+(B*C-(D/E-F)*G)*H ^B+A) +*( 5E^DC Print
Step 4. Reverse the expression. B+A) +*(^ 5E^DC Push
+A) +*(^ 5E^DCB Print
+*+A^BCD^E5 A) +*(+ 5E^DCB^ Pop And Push
) +*(+ 5E^DCB^A Print
End +* 5E^DCB^A+ Pop Until '('
End Empty 5E^DCB^A+*+ Pop Every element

Example infix to prefix 68


Queue

69
Basic Idea
• Queue is an abstract data structure, somewhat similar to Stacks. Unlike
stacks, a queue is open at both its ends. One end is always used to
insert data (enqueue) and the other is used to remove data (dequeue).

70
Queue Representation

• As in stacks, a queue can also be implemented using Arrays, Linked-


lists, Pointers and Structures.

71
enqueue

dequeue

create
QUEUE
isempty

size

72
QUEUE: First-In-First-Out (FIFO)
void enqueue (queue *q, int element);
/* Insert an element in the queue */
int dequeue (queue *q);
/* Remove an element from the queue */
queue *create();
/* Create a new queue */
int isempty (queue *q);
/* Check if queue is empty */
int size (queue *q);
/* Return the no. of elements in queue */

Assumption: queue contains integer elements!

73
Queue using Linked List

74
Basic Idea
• Basic idea:
• Create a linked list to which items would be added to one end and
deleted from the other end.
• Two pointers will be maintained:
• One pointing to the beginning of the list (point from where
elements will be deleted).
• Another pointing to the end of the list (point where new
elements will be inserted). Rear

Front DELETION INSERTION


75
Queue: Linked List Structure

ENQUEUE

front rear

76
Queue: Linked List Structure

DEQUEUE

front rear

77
Example :Queue using Linked List
struct qnode void enQueue(struct Queue* q, int k)
{ {
int val; // Create a new LL node
struct qnode *next; struct QNode* temp = newNode(k);
};
// If queue is empty, then new node is front and rear both
struct queue if (q->rear == NULL) {
{ q->front = q->rear = temp;
struct qnode *front, *rear;
return;
};
typedef struct queue QUEUE; }

// Add the new node at the end of queue and change rear
q->rear->next = temp;
q->rear = temp;
}

78
Example :Queue using Linked List
int size (queue *q)
{
queue *q1; // Function to remove a key from given queue q
int count=0; void deQueue(struct Queue* q)
q1=q; {
while(q1!=NULL) // If queue is empty, return NULL.
{ if (q->front == NULL)
q1=q1->next; return;
count++;
} // Store previous front and move front one node ahead
return count; struct QNode* temp = q->front;
}
q->front = q->front->next;

int peek (queue *q) // If front becomes NULL, then change rear also as NULL
{ if (q->front == NULL)
queue *q1; q->rear = NULL;
q1=q;
while(q1->next!=NULL)
q1=q1->next; free(temp);
return (q1->val); }
}

79
*Queue
Data structure with First-In First-Out (FIFO) behavior

Out
In

B A
C B A

80
*Typical Operations on Queue
REAR
Enqueue

isempty: determines if the queue is empty


isfull: determines if the queue is full
in case of a bounded size queue
front: returns the element at front of the queue
enqueue: inserts an element at the rear
dequeue: removes the element in front

Dequeue

81 FRONT
*Possible Implementations
Linear Arrays:
(static/dynamicaly allocated) Front=> index of the first
element -1

front rear Rear=> index of the last


element

82
*Possible Implementations
Linear Arrays: Linear Arrays:
(static/dynamicaly allocated) (static/dynamicaly allocated)

3 7 1

front rear front rear

Linear Arrays:
(static/dynamicaly allocated)

Queue Full!
3 7 1 8 0 9 6

83
front rear
*Possible Implementations
Linear Arrays: Linear Arrays:
(static/dynamicaly allocated) (static/dynamicaly allocated)

7 1

front rear front rear

Linear Arrays:
(static/dynamicaly allocated)

Queue Full!
0 9 6

84
front rear
void CreateQueue(qu *q) { //define structure of a queue
q->front = -1; struct queue {
q->rear = -1; int array[MAX];
} int front;
int rear;
//create a function to add new element };
void EnQueue(qu *q, int x){
if(q->rear == (MAX - 1)){ / create a function to check whether
printf("Queue size limit reached.\n"); // the queue is empty or not
} else { void isEmpty(qu *q) {
q->array[++q->rear] = x;
printf("%i is added into the queue.\n", x); if(q->rear == q->front) {
}
} //create a function to return size of the queue printf("Queue is empty.\n");
int size(qu *q) { }
return (q->rear - q->front); else {
} printf("Queue is not empty.\n");
}
}
85
//create a function to delete front element
void DeQueue(qu *q){
if(q->rear == q->front){
printf("Queue is empty.\n");
} else {
int x = q->array[++q->front];
printf("%i is deleted from the queue.\n", x);
}
}

//create a function to get rear element


//create a function to get front element int rearElement(qu *q) {
int frontElement(qu *q) { if(q->rear == q->front) {
if(q->rear == q->front) { printf("Queue is empty.\n");
printf("Queue is empty.\n"); return 0;
return 0; } else {
} else { return q->array[q->rear];
return q->array[q->front + 1]; }
} }
} 86
*Possible Implementations
Linear Arrays:
(static/dynamicaly allocated)
Circular Arrays:
(static/dynamically allocated)

front rear

front
rear

Linked Lists: Use a linear Can be implemented by a 1-d


linked list with insert_rear array using modulus operations
and delete_front operations
87
*Circular Queue
[3] [4]

[2] [5]

[1] [6]

[0] [7]

front=0
rear=0

88
*Circular Queue
[3] [4] rear = 4
[3] [4]
C D
[2] [5]
[2] [5] B
After insertion
A
[1] [6] of A, B, C, D
[1] [6]

[0] [7] front=0 [0] [7]

front=0
rear=0

89
*Circular Queue
[3] [4] rear = 4
[3] [4]
C D
[2] [5]
[2] [5] B
After insertion
A
[1] [6] of A, B, C, D
[1] [6]

[0] [7] front=0 [0] [7]

front=0
rear=0

[3] [4] rear = 4


front=2 C D
[2] [5]

After deletion of
[1] [6] of A, B
90
[0] [7]
front: index of queue-head (always empty – why?)
rear: index of last element, unless rear = front

[3] [4] rear = 3 front=4


[3] [4]

[2] [5]
[2] [5]

[1] [6] [1] [6]

[0] [7] [0] [7]


front=0
rear=0 Queue Empty Queue Full

Queue Empty Condition: front == rear


Queue Full Condition: front == (rear + 1) % MAX_Q_SIZE
91
*Creating and Initializing a
Circular Queue
Declaration
#define MAX_Q_SIZE 100
Create and Initialize
typedef struct {
int key; /* just an example, can have
any type of fields depending
on what is to be stored */ queue Q;
} element;
Q.front = 0;
typedef struct {
element list[MAX_Q_SIZE]; Q.rear = 0;
int front, rear;
} queue;

92
int isfull (queue *q)
{ int isempty (queue *q)
if (q->front == ((q->rear + 1) {
%
MAX_Q_SIZE)) if (q->front == q->rear)
return 1; return 1;
return 0; return 0;
} }

93
*Operations
*Operations
element front( queue *q )
{
return q->list[(q->front + 1) % MAX_Q_SIZE];
}

void enqueue( queue *q, element e)


{
q->rear = (q->rear + 1)%
void dequeue( queue *q )
MAX_Q_SIZE; {
q->list[q->rear] = e; q-> front =
} (q-> front + 1)%
MAX_Q_SIZE;
}
94
Problem With Array Implementation
• The size of the queue depends on the number and order of enqueue
and dequeue.
• It may be situation where memory is available but enqueue is not
possible.
ENQUEUE DEQUEUE
Effective queuing storage area of array gets reduced.
0 N

front
front rearrear

Use of circular array indexing


95
Applications of Queues
• Direct applications:-
• Waiting lists
• Access to shared resources (e.g., printer)
• Multiprogramming

• Indirect applications:-
• Auxiliary data structure for algorithms
• Component of other data structures

96

You might also like