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

Module 2

The document discusses linear data structures and their sequential storage representation. It specifically covers stacks, their implementation using arrays, and dynamic arrays. A stack is defined as a linear data structure where insertions and deletions occur at one end. Stacks follow a Last-In First-Out (LIFO) approach. The document provides examples of stack operations and an array-based implementation in C code. It then discusses implementing stacks using dynamic arrays to allow resizing as needed. The applications of stacks in expression conversion, evaluation, and recursion are covered. Steps to convert expressions from infix to postfix notation using operator precedence and a stack are also outlined.

Uploaded by

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

Module 2

The document discusses linear data structures and their sequential storage representation. It specifically covers stacks, their implementation using arrays, and dynamic arrays. A stack is defined as a linear data structure where insertions and deletions occur at one end. Stacks follow a Last-In First-Out (LIFO) approach. The document provides examples of stack operations and an array-based implementation in C code. It then discusses implementing stacks using dynamic arrays to allow resizing as needed. The applications of stacks in expression conversion, evaluation, and recursion are covered. Steps to convert expressions from infix to postfix notation using operator precedence and a stack are also outlined.

Uploaded by

saikiran110077
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 23

Linear data structure – sequential storage

Module-2
Linear Data Structures and their sequential storage Representation

2.1 Stack
2.1.1 Stack Definition and Examples

stack is an ordered list in which insertions (also called push) and deletions (also called pops ) are
made at one end called the top.

Given a stack S = (a0, ...., an-1), we say that a0 is the bottom element, an-1 is the top element,
and ai is on top of element ai-1, 0 < i < n.

Since the last element inserted into a stack is the first element removed, a stack is also known
as a Last-In-First-Out (LIFO) list.

Illustration of stack operations

Illustration of the push and pop operations

Implementation of stack
Stackis implemented by using a one-dimensional array, stack [MAX_STACK_SIZE], where
MAX is the maximum number of entries.
• The first, or bottom, element of the stack is stored in stack [0], the second in stack [1], and the
ith in stack [i-1].
• Variable top points to the top element in the stack.
• Top= -1 to denote an empty stack.

Array Implementation of a stack of integers


#include<stdio.h>
#define MAX 10
int top= -1,stack[MAX];

void push(int item)


{
if (top==MAX-1)
printf("Stack Overflow\n");
else
CSE@HKBKCE 1
Linear data structure – sequential storage

stack[++top]=item;
}

int pop()
{
int itemdel;
if (top==-1)
return 0;
else
{
itemdel=stack[top--];
return itemdel;
}
}

void display()
{
int i;
if(top==-1)
printf("Stack Empty\n");
else
{
printf("Elements Are:\n");
for(i=top;i>=0;i--)
printf("%d\n",stack[i]);
}
}

void main()
{
int ch,item,num,itemdel;
while(1)
{
printf("\nEnter the Choice\n1.Push\n2.Pop\n3.Display\n4.Exit\n");
scanf("%d",&ch);
switch(ch)
{
case 1: printf("Enter item to be inserted\n");
scanf("%d",&item);
push(item);
break;
case 2: itemdel=pop();
if(itemdel)
printf("\n Deleted Item is:%d\n",itemdel);
else
printf("Stack Underflow\n");
break;
case 3: display();

CSE@HKBKCE 2
Linear data structure – sequential storage

break;
case 4: exit(0);
}
}
}

2.1.3 Stacks Using Dynamic Arrays


If we do not know the maximum size of the stack at compile time, space can be allocated for the
elements dynamically at run time and the size of the array can be increases as needed.

Creation of stack
Here the capacity of the stack is taken as 1. The value of the capacity can be altered specific to
the application

StackCreateS() ::=

int *stack
Stack=(int*)malloc(stack, sizeof(int));
int capacity = 1;
int top = -1;

BooleanIsEmpty(Stack) ::= top < 0;


BooleanIsFull(Stack) ::= top >= capacity-1;

The function push remains the same except that MAX_STACK_SIZE is replaced with capacity
void push(element item)
{
if (top >=capacity-1)
stackFull();
stack[++top] = item;
}

The code for the pop function remains unchanged

element pop()
{/* delete and return the top element from the stack */
if (top == -1)
return stackEmpty(); /* returns an error key */
return stack[top--];
}

Stackfull with Array doubling

The code for stackFull is changed. The new code for stackFull attempts to increase the capacity of the
array stack so that we can add an additional element to the stack. In array doubling, the capacity of the
array is doubled whenever it becomes necessary to increase the capacity of an array.
void stackFull()
CSE@HKBKCE 3
Linear data structure – sequential storage

{
stack=(int*)realloc(stack, 2 * capacity * sizeof(int))
capacity =capacity * 2;
}

Analysis
• In the worst case, the realloc function needs to allocate 2*capacity *sizeof (*stack) bytes of
memory and copy capacity*sizeof (*stack)) bytes of memory from the old array into the new
one.
• Under the assumptions that memory may be allocated in O(1) time and that a stack element can
be copied in O(1) time, the time required by array doubling is O(capacity). The total time spent
in array doubling is of O(n) where n is the total number of push operations.
• Hence even with the time spent on array doubling in the total time of push over all n pushes in
O(n). This conclusion is valid even the stack array is resized by a factor c>1.

2.2 Application of stack


➢ Conversion of Expression
➢ Evaluation of expression
➢ Recursion

2.2.1 Infix, postfix(Suffix) and Prefix(polish)


Expression is a collection of operands and operators
An expression can be represented in three different ways.
➢ Infix expression: operators are in between the two operands . Example a+b
➢ Prefix expression: operators are present before the operands. Example +ab
➢ Postfix expression: operators are present after the operands. Example ab+

The prefixes “pre”, “post”, and “in” refer to the relative position of the operator with respect to the
two operands.

To convert an expression from infix to prefix or postfix we follow the rules of precedence.
Precedence : The order in which different operators are evaluated in an expression is called precendence
Associativity : The order in which operators of same precedence are evaluated in an expression is called
Associativity.

The operators are listed in the order of higher precedence down to lower precedence

Operator Associativity
--,++ left-to-right
Unary operators ,!,-,+, &, Right to left
*,sizeof
*,/,% left-to-right
+,- left-to-right

CSE@HKBKCE 4
Linear data structure – sequential storage

2.2.2 Converting an expression from infix to postfix


The operands in the infix and the postfix expression are in the same order. With respect to operators ,
precedence of operators plays an important role in converting an infix expression to postfix expression.
We make use of the stack to insert the operators according to their precedence.

The following operations are performed to convert an infix expression to postfix.

Scan the symbol character by character


➢ If the symbol is an operand place it in the postfix string
➢ If the symbol is an opening parenthesis push it on to the stack
➢ If the symbol is a closing parenthesis pop the contents of the stack until we see an opening
parenthesis and place it in the postfix string. The opening parenthesis and the closing
parenthesis is not placed in the postfix string.
➢ If the symbol is an operator and if the precedence of the input symbol is more than the
precedence of the symbol on top of the stack, then the operator is pushed on to the stack. If the
precedence of the input symbol is lesser than the symbol on top of the stack we pop each such
operators and place it in the postfix string

Algorithm Polish(Q,P)
Suppose Q is an arithmetic expression written in infix notation. This algorithm finds the equivalent
Postfix expression P.

1. Push ‘(’ on to STACK to identify the end of the stack


2. Scan Q from Left to right and repeat steps 3 to 6 for each character of Q until the end of the
string
3. If an operand is encountered add it to P
4. If a left parenthesis is encountered ,push it to onto STACK.
5. If an operator  is encountered then
a. Repeatedly pop each operator that has equal or higher precedence and add to P.
b. Add  to Stack
6. If a right Parenthesis is encountered, then
a. Repeatedly pop from stack and add to P each operator on top of stack until until a left
parenthesis is encountered.
b. Remove the left Paranthesis.[ do not add left parenthesis to stack]
[End of If Structure.]
[End of Step 2 loop]
7. Repeatedly pop stack until it is empty and add to P
8. Exit

Function to convert an infix expression to postfix

Assume the stack and the top is declared globally


char s[25];
int top=-1;

int precd(char op)

CSE@HKBKCE 5
Linear data structure – sequential storage

{
int r;
switch(op)
{
Case ‘^’:
Case ‘$’ r=3; break;
case '*':
case '/': r=2;break;
case '+':
case '-': r=1;break;
case '(': r=0;break;
case '#': r=-1;break;
}
return(r);
}

void infix_postfix(char infix[],char postfix[])


{
int i,p=0;
char symbol,item;
push('#');
for (i=0;infix[i]!='\0';i++)
{
symbol=infix[i];
switch(symbol)
{
case '(': push(symbol);
break;
case ')':item=pop();
while(item!='(')
{
postfix[p++]=item;
item=pop();
}
break;
case '+':
case '-':
case '*':
case '/':
case '%':while(precd(s[top])>=precd(symbol))
{
item=pop();
postfix[p++]=item;
}
push(symbol);
break;

case '^': while(precd(s[top])>precd(symbol))


{
CSE@HKBKCE 6
Linear data structure – sequential storage

item=pop();
postfix[p++]=item;
}
push(symbol);
break;
default: postfix[p++]=symbol;
break;
}
}
while(top>0)
{
item=pop();
postfix[p++]=item;
}
postfix[p]='\0';
}

Example: Translation of the infix string a*(b+c)*d to postfix

Infix Stack Postfix


Token [0] [1] [2] [3]
a # a
* # * a
( # * ( a
b # * ( ab
+ # * ( + ab
c # * ( + abc
) # * abc+
* # * abc+*
d # * abc+*d
Eos(\0) # abc+*d*

Analysis:
Let n be length of the infix string. (n) time is spent extracting tokens . There are two while loop
where the total time spent is (n) since the number of tokens that get stacked and unstacked is linear
in n . So the complexity of the function is (n)

2.2.3 Evaluating a postfix expression

Each operator in a postfix string refers to the previous two operands in the string. If we are parsing a
string, each time we read operands we push it to the stack and when we read a operator, its operands
will be the two topmost elements in the stack. We can then pop these two operands and perform the
indicated operation and push the result back to the stack so that it can be used by the next operator.

Example: Evaluation of postfix string 6 2 3 + - 3 8 2 / + * 2 $ 3 +

Token Stack content Operand1 Operand2 Result


CSE@HKBKCE 7
Linear data structure – sequential storage

[0] [1] [2] [3]


6 6
2 6 2
3 6 2 3
+ 6 5 2 3 5
- 1 6 5 1
3 1 3
8 1 3 8
2 1 3 8 2
/ 1 3 4 8 2 4
+ 1 7 3 4 7
* 7 1 7 7
2 7 2
$ 49 7 2 49
3 49 3
+ 52 49 3 52

The following function evaluates a postfix expression using a stack.


A stack of float elements is declared globally

float s[25];
int top;

float Evaluate(char *postfix)


{

int i=0;
float res=0,op1,op2;
char symbol;

While(postfix[i]!=’\0’)
{

Symbol=postfix[i];
If isdigit(symbol)
{
Push(symbol-‘0’);
}
Else
{
op2=pop();
op1=pop();
res=operation(symbol,op1,op2);
push(res);
}
}
res=pop();
CSE@HKBKCE 8
Linear data structure – sequential storage

return(res);
}

float operation(char op, float op1,float op2)


{
float res;
switch(op)
{
case '+': res= op1+op2;
case '-': res= op1-op2;
case '*': res= op1*op2;
case '/': res= op1/op2;
case '^': res= pow(op1,op2);
}
return (res);
}

Limitations of the program

➢ It does not check if the postfix expression is valid or not. If we input erroneous expression it
returns wrong result
➢ We cannot enter negative numbers, as the symbol to indicate negation will be misinterpreted as
subtraction operation

Analysis:
Let n be length of the postfix string then the complexity of the function is (n)

Algorithm PostfixEval(P)
This algorithm finds the VALUE of an arithmetic expression P written in postfix notation
1. Scan P from Left to righ
2. Repeats steps 3 and 4 until we reach the end of P
3. If an operand is encountered put it on stack
4. If an operator  is encountered then:
a) remove two top elements of STACK, where A is the top element and B is the next
top- element
b) Evaluate B  A
c) Place the result of (4) in STACK.
[End of If structure]
[End of step 2 Loop]
5. Set VALUE equal to the top element of STACK.
6. EXit

2.3 Recursion
Recursion is the process of defining an object in terms of a simpler case of itself.

Suppose p is a function containing either a call statement to itself (direct recursion) or a call statement
to a second function that may eventually result in a call statement back to the original function
CSE@HKBKCE 9
Linear data structure – sequential storage

P(indirect recursion). Then the function P is called a recursive function.

A recursive function must have the following two properties.


• There must be a certain argument called the base value for which the function will not call
itself.
• Each time the function refers to itself the argument of the function must be closer to the base
value.
A recursive function with these two properties are said to be well defined.

2.3.1 Factorial function

The factorial of a number n is got by finding the product of all the number form 1 to n. ie
1*2*3…*n.. It is represented as n!
Example
4!=4*3*2*1=24
5!=5*4*3*2*1=120
0!=1

From a close observation it can be observed that 5!= 5*4! .


Therefore n!=n*(n-1)!

Accordingly the factorial function can be defined as


Factorial function definition
a) If n=0, then n!=1
b) If n>0, then n!=n*(n-1)!

The definition is recursive since the function refers to itself for all value of n>0.
The value of n! is explicitly given as 1 when the value of n=0 which can be taken as the base value
This can be implemented by the code
factorial(int n)
{
f=1;
for(i=1;i<=n;i++)
f=f*i;
return(f)
}
This is the iterative implementation of the factorial function

The factorial function can be implemented as a recursive function.

For example
factorial (5)=5*factorial(4)
factorial (4)=4*factorial(3)
factorial (3)=3*factorial(2)
factorial(2)=2*factorial(1)

CSE@HKBKCE 10
Linear data structure – sequential storage

factorial(int n)
{
if (n==0 )
return(1);
else
return(n*factorial(n-1))
}

2.3.2 Fibonacci numbers in C

Fibonacci sequence is a sequence of integers. 0 1 1 2 3 5 8 ….. fib(0) =0 and fib(1)=1 then each
element in this sequence is the sum of the previous two numbers.
fib(n)=n if n=0 or if n=1
fib(n)=fib(n-2)+ fib(n-1) if n>=2

Recursive function to generate the nth Fibonacci number


int fib(int n)
{
if (n<=1)
return(n);
else
return(fibo(n-1)+fibo(n-2));
}

Example:
Fibo(4)= fibo(3)+fibo(2)
=fibo(2)+fibo(1)+fibo(2)
=fibo(1)+fibo(0)+fibo(1)+ fibo(2)
= 1+ fibo(0)+fibo(1)+ fibo(2)
=1+0 + fibo(1)+ fibo(2)
=1+0+1+fibo(2)
=2+ fibo(1)+ fibo(0)
=2+1+fibo(0)
=2+1+0= 3

GCD of two numbers


The function accepts two numbers as input and returns the gcd of the two numbers
gcd(int m, int n)
{
If (n==0)
Return m;
retrun(gcd(n,m%n))
}

Example:
gcd(2,0)=2
gcd(0,2)= gcd(2,0)=2
gcd(4,2)= gcd(2,0)=2
CSE@HKBKCE 11
Linear data structure – sequential storage

gcd(7,3)= gcd(3,1)= gcd(1,0)=1

2.3.3 Binary search in C


int binsearch(int *a , int key, int low, int high)
{
If (low>high)
return(-1);
mid=(low+high)/2;
if (key==a[mid])
return(mid)
else
if (key>a[mid])
return(binsearch(a,key,mid+1,high));
else
return(binsearch(a,key,low,mid-1));
}

2.3.4The Tower of Hanoi problem


We have to move n disks from peg A to peg C using peg B as auxiliary disk. The disks are placed in
such a way that the larger disks are always below a smaller disk. Only the top disk on any peg can be
moved to any other peg. Larger disk should never rest on a smaller disk.

A recursive solution to the tower of Hanoi problem is given as follows


To move n disks from A to c using B as auxiliary

➢ If n==1 move the single disk from A to C and stop


➢ Move the top n-1 disks form A to B using C as auxiliary
➢ Move the nth disk from A to C
➢ Move n-1 disk from B to C using A as auxiliary

Write a program to solve the Tower of Hanoi problem using a recursive function
void tower(int n,char source,char temp,char dest)
{
if(n==1)
{
printf("Move disc 1 from %c to %c\n",source,dest);
count++;
return;
}
tower(n-1,source,dest,temp);
printf("Move disc %d from %c to %c\n",n,source,dest);
count++;
tower(n-1,temp,source,dest);
}
Void main()
{
int n,count;
printf("Enter the number of discs\n");
scanf("%d",&n);
CSE@HKBKCE 12
Linear data structure – sequential storage

tower(n,'A','B','C');
printf("The number of moves=%d\n",count);
}

Example: n=3 disks

Tracing of function with n=3 disks

Tower(3,A,B,C)

Tower(2,A,C,B) Move 3 A-> C Tower(2,B,A,C)

Tower(1,A,B,C) Move 2 A-> B Tower(1,C,A,B) Tower(1,B,C,A Move 2 B->C Tower(1,A,B,C)


Move 1 A->c Move 1 C-> B Move 1 B->A Move 1 A-> C

The moves for n=3 disk is summarized below.


Move 1 from A to C
Move 2 from A to B
Move 1 from C to B
Move 3 from A to C
Move 1 from B to A
Move 2 from B to C
Move 1 from A to C

Note: Ideal number of moves to solve Tower of Hanoi is given as 2n -1 where n is the total number of
disks

Problem solved with n=3 disks

2.3.5 Ackermann Function


The Ackermann function is a function with two arguments each of which can be assigned any non
negative integer 0,1,2………. . This function finds its application in mathematical logic.
This function is defined as follows
a) If m = 0 then A(m,n) = n + 1
b) If m != 0 but n = 0 then A(m,n) = A(m - 1,1)
c) If m != 0 and n != 0 then A(m,n) = A(m - 1, A(m,n - 1))

CSE@HKBKCE 13
Linear data structure – sequential storage

The function is given as follows


int A(int m,int n)
{
if (m == 0)
return(n+1);
if ((m !=0) && (n== 0 ))
return(A(m-1,1));
if ((m!= 0) && (n != 0))
return(A(m-1, A(m,n-1)));
}

Example1:
A(1,2) =A(0,A(1,1))
=A(0,A(0,A(1,0)))
= A(0,A(0,A(0,1))
=A(0,A(0,2)
=A(0,3)
4

Example 2:

A(1,3) = A(0,A(1,2))
=A(0,A(0,A(1,1)))
=A(0,A(0,A(0,A(1,0))))
=A(0,A(0,A(0,A(0,1))))
=A(0,A(0,A(0,2)
=A(0,A(0,3)
=A(0,4)
5

Disadvantages of using Recursion


• Non recursive version of the program is more efficient when compared to recursive version in
terms of time and space
• Non recursive versions do not have the overhead of entering and exiting from the block.
• In recursive program the local variables have to be maintained using a stack,which can be
avoided in an iterative(non recursive) version

Advantage of using Recursion


• Recursive program is the most natural and logical way of solving some of the problems

CSE@HKBKCE 14
Linear data structure – sequential storage

• If a stack can be eliminated in a recursive program without having any local variables then
they can be as fast its non recursive version,

Difference between iterative and recursive functions

Iterative Recursive
Implemented using looping Implemented using recursive calls to
statements functions
Executes faster Takes more time to execute
Memory utilization is Less Memory utilization is more
Lines of code are more Lines of code are lesser
Does not require stack Implementation requires stack

2.4 Queues
A queue is an ordered list in which insertions and deletions take place at different ends. The end at
which new elements are added is called the rear, and that from which old elements are deleted is
called the front. Queues are also known as First-In-First-Out (FIFO) lists.

The ADT specification of the queue


objects: a finite ordered list with zero or more elements.
functions: for all queue∈Queue, item∈element, maxQueueSize∈ positive integer

Queue CreateQ(maxQueueSize) ::= create an empty queue whose maximum size is


maxQueueSize
BooleanIsFullQ(queue, if (number of elements in queue == maxQueueSize)
maxQueueSize) ::= returnTRUE
else returnFALSE

QueueAddQ(queue, item) ::= if (IsFullQ(queue)) queueFull


else insert item at rear of queue and return queue
BooleanIsEmptyQ(queue) ::= if (queue == CreateQ(maxQueueSize))
returnTRUE
else returnFALSE
Element DeleteQ(queue) ::= if (IsEmptyQ(queue)) return
else remove and return the item at front of queue.
F

Example
Initially f =-1 r=-1 queue empty

Element
index [0] [1] [2] [3] [4] [5]

CSE@HKBKCE 15
Linear data structure – sequential storage

f=-1
Insert 3
Element 3
index [0] [1] [2] [3] [4] [5]
,r

f=-1
Insert 5
Element 3 5
index [0] [1] [2] [3] [4] [5]
r

f=-1
Insert 7
Element 3 5 7
index [0] [1] [2] [3] [4] [5]
R

delete
Element 5 7
index [0] [1] [2] [3] [4] [5]
f R

Deleted item =3

2.4.1 C implementation of queues for an integer array


A queue can be represented by using an array to hold the elements of the array and to use two
variables to hold the position of the first and last element of the queue.

#define size 10

int q[size];
int front=-1 ,rear=-1;

The condition where the queue is empty is called queue underflow.


When we define the size of the array, we cannot insert elements more than the size of the array, this
CSE@HKBKCE 16
Linear data structure – sequential storage

condition where the queue is full is called as queue overflow.

Insert operation
The insert operation first checks for queue overflow. If the queue is not full it inserts one element into
the queue at the rear.
Void insert(int item)
{
If rear==size-1)
Printf(“queue overflow”);
Else
{
rear++;
q[rear]=item;
}
}

Delete operation
Delete operation checks for queue underflow condition and if the queue is not empty it will remove
the element at the front.

int delete()
{
Int itemdel;
If (front ==rear)
{
Printf(“queue underflow”);
return(0);
}
Else
{
front++
Itemdel=q[front];
return(itemdel);
}

Display operation
The display operation will display the elements of the queue if the queue is not empty.
Void display(s)
{
If (front==rear)
Printf(“queue empty”);
else
{
for(i=front+1;i<=rear;i++)
printf(“%d”,q[i]);
}
}

Disadvantage of linear queue


CSE@HKBKCE 17
Linear data structure – sequential storage

The following example illustrates the disadvantage of linear queue

f r Q[0] Q[1] Q[2] Q[3] Q[4] Comment


- -1 Queue is empty
-1 0 2 Insert 2
-1 1 2 3 Insert 3
-1 2 2 3 4 Insert 4
-1 3 2 3 4 5 Insert 5
-1 4 2 3 4 5 6 Insert 6
0 4 3 4 5 6 Delete- item
deleted=2
1 4 4 5 6 Delete- item
deleted=3
Insert
3(disadvantage)
Queue full. Element
cannot be inserted
since rear= size-1

Even if the queue is empty since the value of rear= size-1 elements cannot be inserted into the queue.
This is the disadvantage of linear queue.

2.4.3 Circular Queue


In a circular queue the queue is arranged in a circular fashion. It is a more efficient representation of
queue.

Example:
Insert 3 Insert 5

Empty Queue
5

[ [ 3
3
2 3
[ ] ] [
1 [0] [5] 4 Front=0 rear=1 Front=0 rear=2
] ]
Front=0 rear=0
Insert 7 Insert 9 delete

CSE@HKBKCE 18
Linear data structure – sequential storage

7
5 7 5 5 7

3 9 9
3

Front=0 rear=3 Front=0 rear=4 Front=1 rear=4

Implementation of circular queue for an array of integers

Modification in code to implement circular queue


• Initial value of front and rear=0
• To advance the pointer from size-1 to 0 the code rear++ is modified to rear=(rear +1)%size
and the code front++ is modified to front=(front+1)%size
• Initially when front=0 rear=0 i.e when front == rear the queue is empty now after 6 insertions
are made again fron=0 and rear= 0 that is the queue is full. So, we cannot distinguish between
an empty and a full queue.
• To avoid the resulting confusion, the value of the rear is incremented before we check for the
condition front == rear for queue overflow.

#define MAX_QUEUE_SIZE 6
int q[size];
int front=0 ,rear=0;

Insert operation
The insert operation first checks for queue overflow. If the queue is not full it inserts one element into
the queue at the rear.

void addq(element item)


{
if (front == (rear+1) % MAX_QUEUE_SIZE )
printf(“Queue full”);
else
{
rear= (rear+1) % MAX_QUEUE_SIZE
queue[rear] = item;
}

Delete operation
Delete operation checks for queue underflow condition and if the queue is not empty it will remove
the element at the front.

element deleteq()
{
element item;
if (front == rear)
CSE@HKBKCE 19
Linear data structure – sequential storage

return queueEmpty();
front = (front+1) % MAX_QUEUE_SIZE;
return queue[front];
}

2.4.4 Circular Queues Using Dynamically Allocated Arrays

• To add an element to a full queue, we must first increase the size of this array using a function
such as realloc.
• As with dynamically allocated stacks, we use array doubling. However, it isn't sufficient to
simply double array size using realloc.
• Consider the full queue . This figure shows a queue with seven elements in an array whose
capacity is 8. To visualize array doubling when a circular queue is used, the array is flattened
out as shown in the array of Figure (b).

Figure (c) shows the array after array doubling by realloc.

To get a proper circular queue configuration, The number of elements copied can be limited to capacity
- 1 by customizing the array doubling code so as to obtain the configuration as shown below.

This configuration may be obtained as follows:


1. Create a new array newQueue of twice the capacity.
2. Copy the second segment (i.e., the elements queue [front + 1] through queue [capacity -
1 ]) to positions in newQueuebeginning at 0.
CSE@HKBKCE 20
Linear data structure – sequential storage

3. Copy the first segment (i.e., the elements queue [0] through queue [rear]) to positions
in newQueue beginning at capacity-front-1.
Function to add to a circular queue has no change
void addq(int item)
{
rear = (rear+1) % capacity;
if (front == (rear+1) % capacity)
queueFull(); /* double capacity */
else
{
rear = (rear+1) % capacity;
queue[rear] = item;
}

Function to double queue capacity


void queueFull()
{
int* newQueue;

newQueue=(int*)malloc( 2 * capacity * sizeof(int));


/* copy from queue to newQueue */
int start = (front+1) % capacity;
if (start < 2)
copy(queue+start, queue+start+capacity-1, newQueue);
else
{ /* queue wraps around */
copy(queue+start, queue+capacity, newQueue);
copy(queue, queue+rear+1, newQueue+capacity-start);
}

/* switch to newQueue */
front= 2 * capacity - 1;
rear = capacity - 2;
capacity *= 2;
free(queue);
queue = newQueue;
}

The function copy(a,b,c) copies elements from locations a through b-1 to locations beginning at c

2.4.5 Deques
A deque (pronounced either as deck or dequeue) is a linear list in which elements can be added or
removed at either end but not in the middle. The term deque is a contraction of the name double ended
queue.

CSE@HKBKCE 21
Linear data structure – sequential storage

Representation: It is represented as a circular array deque with pointers left and right, which point to
the two ends of the queue. It is assumed that the elements extend from the left end to the right end in
the array. The term circular comes from the fact that DEQUE[0] comes after DEQUE[n-1] in the array.

Example1:
Left=2 A B C
Right=4
[0] [1] [2] [3] [4] [5] [6]

Example2:
Left=5 A B D E
Right=1
[0] [1] [2] [3] [4] [5] [6]

There are two types of deque:


Input restricted:- insertion is allowed only at one end, deletion is allowed at both ends.
Output restricted: deletion is allowed only at one end, insertion is allowed at both ends

2.4.6 Priority queue


A priority queue is a collection of elements such that each element has been assigned a priority such
that the order in which the elements are deleted and processed comes from the following rules.
1. An element of higher priority is processed before any element of lower priority.
2. Two elements with the same priority are processed according to the order in which they were
added to the queue.

Example: Time sharing system: programs of higher priority are processed first and programs with the
same priority form a standard queue.

Representation using multiple queue


Use a separate queue for each level of priority. Each queue will appear in its own circular array and
must have its own pair of pointers, front and rear. If each queue is allocated the same amount of space,
a two dimensional array can be used instead of the linear arrays.

Example : consider the queue given below with the jobs and its priorities and its representation. A job
with priority 1 is considered to have the highest priority

J1 1
J2 1
J3 2
J4 4
J5 4
J6 6

The queue is represented as a two dimensional array as shown below

Front rear 0 1 2 3 4 5
0 0 2 0 J1 J2
CSE@HKBKCE 22
Linear data structure – sequential storage

1 0 1 1 J3
2 0 0 2
3 2 4 3 J4 J5
4 4
5 0 1 5 J6

Delete operation
Algorithm:
1. Find the smallest k such that front[k]!=rear[k] ie Find the first non empty queue
2. Delete the process at the front of the queue
3. Exit

Insert operation
Algorithm: this algorithm adds an ITEM with priority number P to a priority queue maintained by a
two dimensional array
1. Inset ITEM as the rear element in row P-1 of queue
2. exit

CSE@HKBKCE 23

You might also like