Data Structure Using C Bsc-IV
Data Structure Using C Bsc-IV
Introduction :
Data structure is a method of storing data in a computer so that it can be used efficiently.
The data structures mainly deal with :
Primitive data structures : Primitive data are basic data structure. These are operated directly by
machine instructions. Primitive data structures are implemented at most primitive level.
Examples : integers, float, char and double.
Non-primitive Data structures : These are more sophisticated data structures. These are derived
from primitive data structures. The non-primitive data structures are again classified into two
categories. They are :
Linear Data Structures : Data structures which shows relationship of adjacency between
elements is said to be linear. Examples of linear data structures include array, list, stack,
queue, circular queue, linked list.
Nonlinear Data Structures : Data structures which do not show relationship of adjacency
between elements is said to be nonlinear. Examples of nonlinear data structures include
trees, graphs and files.
Integer
Floating Point
Double Stacks
Pointer
Data structures Queues
Definition :
A Stack is special type of data structure (an ordered collection of items) where elements are
inserted from one end and elements are deleted from the same end. This position from where
elements are inserted and from where elements are deleted is called top of stack. Using this
approach, the last element inserted is the first element to be deleted out, and hence, stack is also
called Last In First Out (LIFO) data structure. The operations that can be performed on stacks are
shown below :
Stack Operations :
Inserting an element into the stack is called Push operation. Only one item is inserted at a
time and item has to be inserted only from top of the stack.
Example : Stack contents after inserting 4 items 30, 20, 25 and 10 one after other with a STACK_SIZE
4. STACK_SIZE = 4
top
3 3 3 3 3 10
top
2 2 2 2 25 2 25
top
1 1 1 20 1 20 1 20
top
0 0 30 0 30 0 30 0 30
top
-1 s s s s s
In the above given example with STACK_SIZE 4. We can insert at the most four elements.
After inserting 30, 20, 25 and 10 there is no space to insert any item. Then we say that stack is full.
This condition is called overflow of stack.
Before inserting any element, we should ask the question “Where and how the item has to
be inserted ?” Let us consider the situation where two elements are 30 and 20 are already inserted
into the stack as shown in below figure 2.a with top = 1
STACK_SIZE = 4
top
3 3 3 3 15
top top
2 2 2 25 2 25
top
1 20 1 20 1 20 1 20
0 30 0 30 0 30 0 30
-1 s -1 s -1 s -1 s
(a) (b) (c) (d)
Suppose, we have to insert an element say item. It has to be inserted at top = 2. For this to
happen, we have to increment top by 1 (figure 2.b). This is achieved using the statement
Then item has to be inserted at top position, this is archived by copying item to s[top] (figure 2.c)
using the following statement
We cannot insert any item when top has already reached STACK_SIZE – 1 (figure 2.d). In such
situation, we have to display appropriate message as shown below ;
/* Check for overflow of stack */
if (top = = STACK_SIZE – 1)
printf(“Stack Overflow\n”);
return;
void push()
if(top ==STACK_SIZE – 1)
printf(“Stack Overflow\n”);
return;
}
Note : The array s, the variable top and the variable item are global variables and should be declared
before all the functions.
Re-write the above code by passing parameters. It is clear from the above code as the item is
inserted, the contents of the stack identified by s and the index top pointing to topmost element are
changed and so they should be passes as parameters (pass by reference) as shown below :
if(*top ==STACK_SIZE – 1)
printf(“Stack Overflow\n”);
return;
Note : By comparing functions shown in 2.1.1 and 2.1.2 note that body of the function has not been
changed. But, the type of formal parameters changes.
2.2 Pop Operation :
Deleting an element from the stack is called pop operation. Only one item can be deleted at
a time and item has to be deleted only from top of the stack.
Example : Performing pop operation when stack already contains 30, 20, 25 and 10.
STACK_SIZE = 4
top
3 10 3 3 3 3
top
2 25 2 25 2 2 2
top
1 20 1 20 1 20 1 1
top
0 30 0 30 0 30 0 30 0
top
s s s s -1 s
The items can be deleted one by one as shown in above figure. The contents of stack and the
top which contains the position of topmost elements are also shown.
Stack Underflow : When elements are being deleted, t here is a possibility of stack being empty.
When stack is empty, it is not possible to delete any item. Trying to delete an element from an
empty stack results in stack underflow.
In the above given example after deleting 10, 25, 20 and 30 there are no elements in the
stack and stack is empty. Deleting an element from the stack results in stack underflow.
Implementation of Pop operation using arrays (static allocation technique) :
Let us, delete an item from the top of the stack. This can be achieved by accessing the top
element s[top] as shown below :
top = top – 1;
The above two statements can also be written using single statement as shown below :
Each time, the item is deleted, top is decremented and finally, when the stack is
empty the value of top will be -1 and so, it is not possible to delete any item from the stack.
Hence, the above statement has to be executed only if stack is not empty and the code to
delete an item from stack can be written as shown below :
int pop()
int item_deleted;
if (top == -1)
return item_deleted;
}
Re-write the above function without using global variables and by passing appropriate
parameters. We know that to access the top item, we need the index top and the stack s. So, we
have to pass top and s as the parameters. As the value of top changes every time the item is deleted,
top can be used as a pointer variable. The C function (by passing parameters) is shown below :
/* stack underflow */
if(*top == -1)
return 0;
/* obtain the top most element and change the position of top item */
item_deleted = s[(*top)--];
return item_deleted;
In the display procedure, if the stack already has some items, all those items are displayed
one after the other. If no items are present, the appropriate error message is displayed.
Usually, the contents of the stack are displayed from the bottom to top. So, first item to be
displayed is 30, next item to be displayed is 20 and final item to be displayed is 25. This can be
achieved using the following statements :
for (i = 0; i <= top ; i++)
printf(“%d\n”,s[i]);
But, the above statement should not be executed when stack is empty i.e., when top takes
the value -1. So, the above code can be modified to include this error condition and can be written
as shown below :
Example 2.3.1 : C function to display the contents of stack (using global variables)
void display()
int i;
/* If stack is empty */
if(top == -1)
printf(“Stack is empty\n”);
return;
printf(“%d\n”,s[i]);
}
Example 2.3.2 : C function to display the contents of stack (by passing parameters)
int i;
/* If stack is empty */
if(top == -1)
printf(“Stack is empty\n”);
return;
printf(“%d\n”,s[i]);
}
/* Program to Implement Stack using arrays (using global variables) */
# include<stdio.h>
# include<conio.h>
# include<process.h>
# define STACK_SIZE 5
/* global variables */
int top; /* index to hold the position of the top most item */
void main()
for( ; ; )
printf(“\n 1. Push”);
printf(“\n 2. Pop”);
printf(“\n 3. Display”);
printf(“\n 4. Exit”);
scanf(“%d”, &choice);
switch(choice)
case 1:
scanf(“%d”,&item);
push();
break;
case 2:
item_deleted = pop();
if(item_deleted == 0)
printf(“Stack is empty\n”);
else
case 3:
display();
break;
case 4:
exit(0);
default:
printf(“Invalid Choice\n”);
break;
}
/* Program to Implement Stack using arrays (by passing parameters) */
# include<stdio.h>
# include<conio.h>
# include<process.h>
# define STACK_SIZE 5
void main()
for( ; ; )
{
printf(“\n 1. Push”);
printf(“\n 2. Pop”);
printf(“\n 3. Display”);
printf(“\n 4. Exit”);
scanf(“%d”, &choice);
switch(choice)
case 1:
scanf(“%d”,&item);
break;
case 2:
if(item_deleted == 0)
printf(“Stack is empty\n”);
else
break;
case 3:
display(top, s);
break;
case 4:
exit(0);
default:
printf(“Invalid Choice\n”);
break;
Applications of Stack :
Expression :
The sequence of operators and operands that reduces to a single value after evaluaiton is
called an expression. The operands consists of constants and variables whereas the operators
consists of symbols such as +, -, *, / and so on. The operators indicate the operation to be performed
on the operands specified. The expressions can be represented as shown below :
Infix expression
Prefix expression
In the expression, a + b
operand1 operand2
operator
Note : Since the operator is in between two operands, it is called infix expression.
Postfix Expression : In an expression, if an operator follows the two operands (i.e., operator comes
after the two operands) the expression is called postfix expression. No, parenthesis is allowed in
postfix expressions. The postfix expression is always un-parenthesized. It is also
Prefix Expression : In an expression, if an operator precede the two operands (i.e., operator comes
before the two operands), the expression is called prefix expression. No, parenthesis is allowed in
prefix expressions. The prefix expression is always un-parenthesized. It is also called polish
expression.
Precedence and associativity of the operators : We know that while evaluating the expressions,
some expressions are given precedence over other expression and are evaluated first and some are
evaluated later. These rules that determine the order in which different operators are evaluated are
called precedence rules or precedence of operators.
6*(2+3)– 5 Brackets have the highest precedence and are evaluate first
25 Final result
Normally we associate values to determine the order in which the operators have to
evaluate. Highest precedence operators will have the highest value and lowest precedence
operators will have the least value. The table below shows arithmetic operators along with priority
values
Description Operator Priority Associativity
Note : The symbol ‘$’ or ‘^’ is considered as the operator to perform exponentiation and should be
given first precedence since it has higher priority value. The addition or subtraction is given the least
precedence since it has least priority value as shown in above table.
Associativity of the Operator : During evaluation, if two or more operators have the same
precedence, then precedence rules are not applicable. Instead we go for associativity of the
operators. The order in which the operators with same precedence are evaluated in an expression is
called associativity of the operator. In such case, precedence rules are not considered.
Example : What is the result of 8 + 4 3 ? All of us evaluate the expression as shown below :
8 + 4 + 3
12 + 3
15
Observation : In the above expression, same operator ‘+’ is used twice and hence both operators
have the same priority and the precedence rules are not applicable. So, we do the evaluation as
shown below :
Since evaluation is done from left to right one after the other, we say that the operator ‘+’ is
left to right associative (also called left associative).
Left to Right associative or Left associativity : In an expression, if there are two or more operators
having the same priority and are evaluated from left to right, then the operators are called left
associative operators (Left to Right associative operators). It is normally denote using L R. The
process of evaluating from left to right is called left associativity.
Note : In mathematics 232. We know that 232 = 512. It is not 64. So, to get the answer 512, the
computer has to evaluate the expression 2 $ 3 $ 2 as shown below,
2 $ 3 $ 2
2 $ 9
512
Observation : In the above expression, same operator ‘$’ is used twice and both operators have the
same priority and the precedence rules are not applicable. So we do the evaluation as shown below :
Since evaluation is done from right to left one after the other, we say that the operator ‘$’ is
right – to – left associative (also called right associative).
Right to Left Associative or Right Associative : In an expression, if there are two or more operators
having the same priority and if they are evaluated from right to left, then the operators are called
right associative operators.
For example : $ (representing exponentiation operator. Note : This is not C language operator) is a
right associative operator.
Note : Normally evaluate the expressions by considering infix expression. But, evaluating postfix or
prefix expressions is much easier and efficient. Also, while evaluating postfix or prefix expressions,
we need not worry about the precedence of operators and associativity of operators where as while
evaluating infix expressions, we should know the precedence of operators and whether the
operators are left associative or right associative.
2.4 Conversion from Infix to Postfix
Solution : We can convert into postfix expression based on precedence and associativity as shown
below :
T1 T1 = BC –
T2 T2 = T1 D *
T3 T3 = A T2 +
T4 T4 = T3 E ^
T4 F +
T3 E ^ F + (Replacing T4 by T3 E ^)
A T2 + E ^ F + (Replacing T3 by A T2 +)
A T1 D * + E ^ F + (Replacing T2 by T1 D *)
ABC–D*E^F+ (Replacing T1 by BC –)
Solution : We can convert into postfix expression based on precedence and associativity as shown
below :
T1 T1 = YZ $
T2 T2 = X T1 $
T3 T3 = P Q /
T4 = T2 M –
T5 T5 = T4 N +
T5 + T3
T4 N + P Q / + (Replacing T5 by T4 N + and T3 by P Q /)
T2 M – N + P Q / + (Replacing T4 by T2 M –)
X T1 $ M – N + P Q / + (Replacing T2 by X T1 $)
XYZ$$M–N+PQ/+ (Replacing T1 by Y Z $)
Hence equivalent postfix expression is X Y Z $ $ M – N + P Q / +
RECURSION
Definition : A function which calls itself is called Recursive function. In recursion, the calling function
and called function are same.
Types of Recursion :
{ {
fun_1( ); fun_2( );
} }
fun_2( )
fun_1( );
Recursive Process :
The factorial of a number n is the product of integer values from 1 to n. The recursive
definition to compute n! is given below,
1 if n = 0
fact(n) =
n x fact(n -1) if n > 0
5! = 5 * 4!
Decompose the problem from top to bottom
4! = 4 * 3!
3! = 3 * 2!
2! = 2 * 1!
1! = 1 * 0!
1! = 1 * 0! = 1
2! = 2 * 1! = 2
3! = 3 * 2! = 6
4! = 4 * 3! = 24
5! = 5 * 4! = 120
Note : Thus, it is clear from the above computations, that recursive solution for a problem involves a
two-way journey with a stop at the middle :
Decompose the problem from top to bottom which involves reducing the problem into smaller
problems of same type.
Arrive at the solution which does not involve any recursion. (Base Case)
Compute the solution from bottom to top using the previous solutions.
int fact(int n)
{
if (n = = 0)
return 1; /* Factorial of n when n = 0 */
return n * fact(n – 1) /* Factorial of n when n > 0 */
}
void main( )
{
int n;
clrscr( );
printf(“Enter the value for n\n”);
scanf(“%d”,&n);
printf(“The factorial of %d = %d\n”,n,fact(n));
}
Input :
Enter the value of n
Output