Module 2
Module 2
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.
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.
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);
}
}
}
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;
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;
}
element pop()
{/* delete and return the top element from the stack */
if (top == -1)
return stackEmpty(); /* returns an error key */
return stack[top--];
}
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.
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
Algorithm Polish(Q,P)
Suppose Q is an arithmetic expression written in infix notation. This algorithm finds the equivalent
Postfix expression P.
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);
}
item=pop();
postfix[p++]=item;
}
push(symbol);
break;
default: postfix[p++]=symbol;
break;
}
}
while(top>0)
{
item=pop();
postfix[p++]=item;
}
postfix[p]='\0';
}
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)
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.
float s[25];
int top;
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);
}
➢ 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
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
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
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))
}
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
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
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
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);
}
Tower(3,A,B,C)
Note: Ideal number of moves to solve Tower of Hanoi is given as 2n -1 where n is the total number of
disks
CSE@HKBKCE 13
Linear data structure – sequential storage
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
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,
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.
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
#define size 10
int q[size];
int front=-1 ,rear=-1;
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]);
}
}
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.
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
#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.
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];
}
• 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).
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.
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;
}
/* 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]
Example: Time sharing system: programs of higher priority are processed first and programs with the
same priority form a standard queue.
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
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