Sei sulla pagina 1di 96

INTRODUCTION AND OVERVIEW

INTRODUCTION
This chapter introduces the subject of data structures and presents a detail description of data
organization and data structures along with a discussion of the different operations which are
applied to these data structures. We will also introduce the notion of an algorithm and its
complexity, and also the time -space tradeoff that may occur in choosing a particular algorithm and
data structure for a given problem.
BASIC TERMINOLOGY; ELEMENTARY DATA ORGANIZATION
Data are simply values or sets of values . A data item refers to a single unit of values. Data items
that are divided into sub items are called group items; those that are not are called elementary
items. Collections of data are frequently organized into a hierarchy of fields, records and files. In
order to make these terms more precise we introduce some additional terminology.
An entity is something that has certain attributes or properties which may be assigned values. The
values themselves may be either numeric or nonnumeric.
DATA STRUCTURES
Data may be organized in many ways ; the logical or mathematical model of a particular
organization of data is called a data structure. The choice of a particular data model depends on
two considerations. First, it must be rich enough in structure to mirror the actual relationships of
the data in the real world. On the other hand, the structure should be simple enough that one can
effectively process the data when necessary. Some of the data structures commonly used are :
Arrays, Linked Lists, Stacks, Queues, Trees etc.
These data structures are discussed in detail later in the chapter.
DATA STRUCTURE OPERATIONS
The data appearing in our data structures are processed by means of certain operations. In fact,
the particular data structure that one chooses for a given situation depends largely on the
frequency with which specific operations are performed. This section introduces the reader to some
of the most frequently used of the operations.
The following four operations play a major role in this text:
Traversing: Accessing each record exactly once so that certain items in the
record may be processed. ( This accessing and processing is sometimes called visiting the
record.)
Searching: Finding the location of the record with a given key value ,
or finding the locations of all records which satisfy one or more conditions.
Inserting: Adding a new record to the structure.
Deleting: Removing a record from the structure.
Sometimes two or more of the operations may be used in a given situation; e.g., we may want to
delete the record with a given key, which may mean we first need to search for the location of the
record .
The following two operations which are used in a given special situations, will also be considered:
Sorting: Arranging the records in some logical order (e.g., alphabetically according to some NAME
key, or in numerical order according to some NUMBER key, such as social security number or
account number)
Merging: Combining the records in two different sorted files into a single sorted file .
ALGORITHMS : COMPLEXITY, TIME-SPACE TRADEOFF
An algorithm is well-defined list of steps for solving a particular problem. One major purpose of this
text is to develop efficient algorithms for the processing of our data. The time and space it uses are
two major measures of the efficiency of an algorithm. The complexity of an algorithm is the
function which gives the running time and/or space in terms of the input size.
Each of our algorithms will involve a particular data structure. Accordingly, we may not always be
able to use the most efficient algorithm, since the choice of data structure depends on many
things, including the type of data and the frequency with which various data operations are
applied. Sometimes the choice of data structure involves a time-space tradeoff: by increasing the
amount o space for storing the data, one may be able to reduce the time needed for processing the
data, or vice versa.
MATHEMATICAL NOTATION AND FUNCTIONS
This section gives various mathematical functions which appear very often in the analysis of
algorithm and in computer science in general, together with their notation.
Floor and Ceiling Functions
Let x be any real number. Then x lies between two integers called the floor and the ceiling of x .
Specifically,
, called the floor of x, denotes the greatest integerx- that does not exceed x.
, called the ceiling of x, denotes the leastx integer that is not less than x.
= x-If x is itself an integer, then . x + 1 = x-; otherwise x
Remainder Function : Modular Arithmetic
Let k be any integer and let M be a positive integer. Then k(mod M)
(read k modulo M) will denote the integer remainder when k is divided by M. More exactly k(mod
m) is the unique integer r such that k = Mq + r where 0<= r< M
When k is positive, simply divide k by M to obtain the remainder r. Thus 25(mod 7) = 4, 25(mod 5)
= 0, 35(mod 11) = 2
INTEGER AND ABSOLUTE VALUE FUNCTIONS
Let x be any real number. The integer value of x, written INT(x), converts x into an integer by
deleting (truncating) the fractional part of the number. Thus 5) = 2, INT(-8.5) = -8-INT(3.14) =
3, INT(
Observe that according to whether x isx- or INT(x) = xINT(x) = positive or negative.
The absolute value of the real number x, written ABS(x) or | x |, is 0,-defined as the greater of x
or -x. hence ABS(0) = 0, and ,for x ABS(x) = x or ABS(x) = -x, depending on whether x is positive
or negative Thus,
|-15| = 15, |7| = 7, |-3.33| = 3.33, |2.23| = 2.23
We 0, | x | is-note that | x | = | - x | and, for x positive.
Summation Symbol ; Sums
Here we introduce the (the Greek letter sigma).-summation symbol. Consider a sequence
a1,a2,a3,.Then the sums
a1 + a2 + a3 +.+an and am + am+1 +.+ an
will be denoted, respectively, by
n n
aj- aj and -
j=1 j=m
The letter j in the above expressions is called a dummy index or dummy variable. Other letters
frequently used as dummy variables are i, k, s and t.
FACTORIAL FUNCTION
The product of the positive integers from 1 to n, inclusive, is denoted by n! (read n factorial ).
That is, n! = 1.2.3. .(n - 2)(n - 1)n
It is also convenient to define 0! = 1.
PERMUTATIONS
A permutation of a set of n elements is an arrangement of the elements in a given order. For
example, the permutations of the set consisting of the elements a, b, c are as follows:
abc, acb, bac, bca, cab, cba
There are n! permutations of a set of n elements.
COMPLEXITY OF ALGORITHM
The analysis of algorithms is a major task in computer science. In order to compare algorithms, we
must have some criteria to measure the efficiency of our algorithms. This section discusses this
important topic.
Suppose M is an algorithm, and suppose n is the size of the input data. The time and space used
by the algorithm M are the two main measures for the efficiency of M. The time and space is
measured by counting the number of key operations - in sorting and searching algorithms, for
example, the number of comparisons. That is because key operations are so defined that the time
for the other operations is much less than or at most proportional to the time for the key
operations. The space is measured by counting the maximum of the memory needed by the
algorithm.
The complexity of an algorithm M is the function f(n) which gives the running and/or storage space
requirement of an algorithm in terms of the input data. Frequently, the storage space required by
an algorithm is simply a multiple of the data size n. Accordingly, unless otherwise stated or
implied, the term complexity shall refer to the running time of the algorithm.
The following example illustrates that the function f(n), which gives the running time of an
algorithm, depends not only on the size n of the input data but also on the particular data.
EXAMPLE
Suppose we are given an English short story TEXT, and suppose we want to search through TEXT
for the first occurrence of a given 3- letter word W. If W is the 3 -letter word the, then it is likely
that W occurs near the beginning of TEXT, so f(n) will be small. On the other hand, if W is the 3-
letter word zoo, then W may appear in TEXT at all, so f(n) will be large.
The above discussion leads us to the question of finding the complexity function f(n) for certain
cases. The two cases one usually investigates in complexity theory are as follows:
Worst case: the maximum value of f(n) for any possible input
Average case: the expected value of f(n)
Suppose we also consider the minimum possible value of f(n), called the best Case.
The analysis of the average case assumes a certain probabilistic distribution for the input data; one
such assumption might be that all possible permutation of an input data set are equally likely . The
average case also uses the following concept in probability theory. Suppose the number n1, n2, n3,
..,nk occur with respective probabilities p1, p2, p3 ,pk. Then the exception or average value E is
given by
E = n1p1 + n2p2 + .+ nkpk
DETAILED DESCRIPTION OF VARIOUS DATA STRUCTURES
ARRAYS
The simplest type of data structure is a linear (or- one - dimensional) array. By a linear array, we
mean a list of finite number n of similar data elements referenced by a set of an consecutive
numbers, usually 1, 2, 3, .,n. If we choose the name A for the array, then the elements of A are
denoted by the subscript notation
a1, a2, a3, . an
or by parenthesis notation
A(1), A(2), A)3), ..,A(n)
Or by the bracket notation
A[1], A[2], A[3], ..,A[n]
Regardless of the notation, the number K in A[K] is called a subscript and A[K] is called a
subscripted variable.

ONE DIMENSIONAL ARRAY
An array is a collection of similar data elements. An array is also called linear data structures.
There exists a linear relationship between the array elements. The array elements lie in the
computer memory in a linear fashion. The syntax to define an array is :
Data type array name[size];
1 2 3 4 5 6 7
2128 2143 4348 4361 4538 5423 5438
Horizontal representation of an array
RAVERSING ONE DIMENSIONAL ARRAY
Suppose we have an array M that is collection of integer type in the computer memory. If we visit
each and every element in M then this visiting process is called traversing.
TRAVERSING ALGORITHM
The program segment to illustrate the traversing algorithm.
// Array_T.C
/* Traversing a linear array */
/* ARRAY_T.C */
# include<stdio.h>
void traversing_array(int *, int, int);
void input(int *, int, int);
/* Definition of the function*/
void traversing_array(int linear_array[], int l_b, int u_b)
{
int counter;
for(counter = l_b; counter<=u_b; counter++)
{
printf("\n Element at position: %d is %d ", counter, linear_array[counter]);
}
}
/* Defintion of the function*/
void input(int array[], int l_b, int u_b)
{
int counter;
for(counter = l_b; counter<= u_b; counter++)
{
printf("\n Input value for the: %d: ", counter);
scanf("%d", &array[counter]);
}
}
/* Definition of the function */
void main()
{
int a[100];
int lb, ub;
printf("\n Lower limit of the array:");
scanf("%d", &lb);
printf("\n Upper limit of the array:");
scanf("%d", &ub);
input(a, lb, ub);
traversing_array(a,lb,ub);
}
INSERTION IN A ONE DIMENSIONAL ARRAY
It can be visualized that for inserting an element in one - dimensional array, one has to shift all the
elements one position down.
INSERTION ALGORITHM
The program illustrated below implements the above algorithm
/* INSERTING AN ELEMENT INTO LINEAR ARRAY AT SPECIFIED POSITION */
/* ARRAY_I.C */
# include<stdio.h>
int insert_array(char *, int, int, char);
void input(char *, int );
void display(char *, int );
/* Definition of the function */
int insert_array(char array[], int number, int position, char element)
{
int temp = number;
while( temp >= position)
{
array[temp+1] = array[temp];
temp --;
}
array[position] = element;
number = number +1 ;
return(number);
}
/* INPUT FUNCTION TO READ DATA */
void input(char array[], int number)
{
int i;
for(i = 1; i<= number ; i++)
{
fflush(stdin);
printf("\n Input value for: %d: ", i);
scanf("%c", &array[i]);
}
}
/* OUTPUT FUNCTION TO PRINT ON THE CONSOLE */
void display(char array[], int number)
{
int i;
for(i = 1; i<= number; i++)
{
printf("\n Value at the position: %d: %c ", i, array[i]);
}
}
/* main function */
void main()
{
int number;
char array[100];
int position;
char element;
fflush(stdin);
printf("\n Input the number of element into the LIST: ");
scanf("%d", &number);
fflush(stdin);
input(array, number);
printf("\n Entered list as follows:\n");
fflush(stdin);
display(array,number);
fflush(stdin);
printf("\n Input the position where you want add a new
data:");
scanf("%d", &position);
fflush(stdin);
printf("\n Input the value for the position:");
scanf("%c", &element);
number = insert_array(array,number,position,element);
display(array,number);
getch();
}
DELETION FROM ONE DIMENSIONAL ARRAY
Deleting an element or information from the end of an array is simple but deleting an element from
some other position is difficult and requires moving all the element up-word to fill -up the gap into
the array. Before deleting an element from an array one should go through the following points.
Delete an element if is known then find whether is in the array or not.
Delete an element if its value is known. The value is searched in the array.
Update the array.
Deletion Algorithm
Program to implement the above algorithm.
/* DELETING FROM A LINEAR ARRAY AT SPECIFIED POSITION */
# include<stdio.h>
# define s 20
char employ[s][s];
int delete_array(char employ[s][s], int, int, char *);
void input(char emply[s][s], int );
void display(char employ[s][s], int );
/* Definition of the function */
int delete_array(char employ[s][s], int number, int position, char element[])
{
int temp = position;
element = employ[position];
printf("\n Information which we have to delete: %s", element);
while( temp <= number-1)
{
*employ [temp] = *employ[temp+1];
temp ++;
}
number = number - 1 ;
return(number);
}
void input(char employ[s][s], int number)
{
int i;
for(i = 1; i<= number ; i++)
{
fflush(stdin);
printf("\n Input value for: %d: ", i);
gets(employ[i]);
}
}
void display(char employ[s][s], int number)
{
int i;
for(i = 1; i<= number; i++)
{
printf("\n Value at the position: %d: %s", i, employ[i]);
}
}
/* main function */
void main()
{
int number;
int position;
char element[s];
printf("\n Input the number of elements in the array:");
scanf("%d", &number);
fflush(stdin);
input(employ, number);
printf("\n Entered list is as follows:\n");
display(employ, number);
fflush(stdin);
printf("\n Input the position from where you want delete an element:");
scanf("%d", &position);
number = delete_array(employ, number, position, element);
display(employ,number);}
If in a list same information happens to be more than one place then the repeated information is
called duplicate. The removal of such duplicates is very necessary in some application. Because if
some one is accessing an information from a list but does not know about its duplication and
modifying the such information in one place the inconsistency take place.
The algorithm to remove duplicates from a list is as follows:
Duplicate removal Algorithm
Program to implement duplicate removal algorithm
/* DELETING DUPLICATES FROM A LINEAR ARRAY*/
# include<stdio.h>
int status ;
int dup;
int duplicate_array(int *, int);
void input(int *, int );
void display(int *, int );
/* Definition of the function */
int duplicate_array(int array[], int number)
{
int i, j, k;
status = 0;
dup = number;
for(i = 0; i< number-1; i++)
for(j = i+1; j< number; j++)
{
if(array[i] == array[j])
{
number = number - 1 ;
for(k = j; k<number; k++)
array[k] = array[k+1];
status = 1;
j = j - 1;
}
}
if( status ==0)
printf("\n No duplicate is found");
return(dup-number);
}
/* Input function to read data */
void input(int array[], int number)
{
int i;
for(i = 0; i< number ; i++)
{
printf("Input value for: %d: ", i+1);
scanf("%d", &array[i]);
}
}
/* Output function */
void display(int array[], int number)
{
int i;
for(i = 0; i< number; i++)
{
printf("\n Value at the position: %d: %d", i+1, array[i]);
}
}
/* main function */
void main()
{
int number;
int array[100];
int n;
printf("\n Input the number of elements in the list: ");
scanf("%d", &number);
input(array, number);
printf("\n Entered list is as follows:\n");
display(array,number);
n = duplicate_array(array,number);
printf("\nNumber of duplicate elements in the list are: %d", n);
printf("\nAfter removing duplicates from the list, the list is as
follows:");
display(array,number-n);
}
SEARCHING
Suppose a specific INFO information is given in an array. Searching refers to the operation of
finding the location of the INFO in an array or output some massage if INFO does not exists in the
array. The search is said to be successful if INFO appears in the array else it is called unsuccessful.
Some times it is required to add INFO in the array if do not exist.
For more discussion on sorting, searching, and merging, please go through Chapter 4.
Algorithm to find the smallest and largest element in a list:
Algorithm to find Smallest and Largest
Program implementing above algorithm:
/* SEARCHING FOR LARGEST AND SMALLEST ELEMENTS IN A
LINEAR ARRAY */
# include<stdio.h>
int s;
int small, big, temp;
int search_array(int *, int);
void input(int *, int );
void display(int *, int );
/* Definition of the function */
int search_array(int array[], int number)
{
big = small = array[0];
temp = 0;
while(temp < number)
{
if(array[temp] > big)
{
big = array[temp] ;
}
else if(array[temp] < small)
{
small = array[temp];
}
temp ++;
}
s = small;
return(big);
}
/* Input function */
void input(int array[], int number)
{
int i;
for(i = 0; i< number ; i++)
{
printf("Input value for : %d: ",i+1);
scanf("%d", &array[i]);
}
}
/* Output function */
void display(int array[], int number)
{
int i;
for(i = 0; i < number; i++)
{
printf("\n Value at the position: %d: %d", i+1, array[i]);
}
}
/* main function */
void main()
{
int number,big;
int array[100];
printf("\n Input the number of elements in the list:");
scanf("%d", &number);
input(array, number);
printf("\n Entered list is as follows:\n");
display(array,number);
big = search_array(array,number);
printf("\nLargest number in the array is : %d", big);
printf("\nSmallest number in the array is : %d", s);
}
MULTI DIMENSIONAL ARRAYS
Most of the programming languages permit two, three, four, five and more dimensional arrays
where an element is referenced by more than one subscript. If an array is two - dimensional then
two subscripts are used to reference an element in the array. Similarly, if the array is a three -
dimensional then three subscripts are used to reference an element of the array. C, C++, and
Visual C/C++ languages permit 1, 2, 3, 4 or more dimensional arrays, where BASIC language
permit only 1, 2 and 3 dimensional arrays. The advanced versions of BASIC, Visual BASIC permit
arrays as permitted by C, C++ and Visual C/C++ languages.
Row\Column

0 1 2
0 11 33 22
1 22 44 11
2 33 55 99
3 44 66 88
4 55 66 77
TWO DIMENSIONAL ARRAYS
Let Mat is a two dimensional array with Row number of rows and Col number of columns. Then one
may define array Mat as a collection of Row x Col information . Each element of the array Mat is
accessed by specified pairs of integers called subscripts. If I and J are integers and are used to
access information from a two - dimensional array Mat, then there should be following relations
among subscript variable I and J, and rows and columns maximum limit.
I0 < Row
For C, C++, and Visual C/C++ languages
J0 < Col
Row I 1
For other popular languages e.g. FORTRAN etc.
J 1 Col
Two-dimensional arrays are called Matrices in mathematics and table in business applications.
There is a standard way for drawing a two dimensional Row x Col array Mat. The elements of Mat
form a rectangular array with Row rows and Col columns. The element Mat[I][J] appears in row I
and column J. A row is a horizontal list of elements and a column is a vertical list of elements. In
the field of database a row is called a tuple.
COLUMN -------
Mat[0][0] Mat[0][1] Mat[0][2] Mat[0][3] Mat[0][4]
Mat[1][0] Mat[1][1] Mat[1][2] Mat[1][3] Mat[1][4]
Mat[2][0] Mat[2][1] Mat[2][2] Mat[2][3] Mat[2][4]
Mat[3][0] Mat[3][1] Mat[3][2] Mat[3][3] Mat[3][4]
Mat[4][0] Mat[4][1] Mat[4][2] Mat[4][3] Mat[4][4]
Mat[5][0] Mat[5][1] Mat[5][2] Mat[5][3] Mat[5][4]
Two dimensional representation of an array
TRAVERSING TWO DIMENSIONAL ARRAYS
Traversing of a two-dimensional array can be classified into two categories, depending upon the
two types of representation:
(i) Column major order
(ii) Row major order
Algorithm to traverse a two dimensional array in row major order
Algorithm to traverse a two dimensional array in column major order
Program showing the traversing in a two dimensional array
/* TRAVERSING A TWO DIMENSIONAL ARRAY */
# include<stdio.h>
int i, j;
float mat[10][10];
void Traverse ( int, int);
void input( int, int);
/* Display function */
void Traverse (int row, int col)
{
printf("\n Traversing in row major order\n");
for( i = 0; i < row; i++)
{
for( j = 0; j < col; j++)
{
printf("\n 0x%x", &mat[i][j]);
printf(" %f", mat[i][j]);
}
printf("\n");
}
printf("\n Traversing in column major order\n");
for(j = 0; j < col; j++)
{
for(i = 0; i < row; i++)
{
printf("\n 0x%x", &mat[i][j]);
printf(" %f", mat[i][j]);
}
printf("\n");
}
printf("\n Traversing in row major order\n");
for(i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
{
printf(" mat[%d][%d] = ", i, j);
printf("%f", mat[i][j]);
}
printf("\n");
}
printf("\n Traversing in column major order\n");
for(j = 0; j < col; j++)
{
for(i = 0; i < row; i++)
{
printf(" mat[%d][%d] = ", i, j);
printf("%f", mat[i][j]);
}
printf("\n");
}
}
/* Input function */
void input(int row, int col)
{
for(i = 0 ; i< row; i++)
{
for(j = 0 ; j<col; j++)
{
printf("\nInput Value for : %d: %d: ",i+1, j+1);
scanf("%f", &mat[i][j]);
}
}
}
/* main function */
void main()
{
int r,c;
printf("\n Input the number of rows:");
scanf("%d", &r);
printf(" Input the number of cols:");
scanf("%d", &c);
input(r, c);
Traverse(r, c);
}
ALGEBRA OF MATRICES
ADDITION OF MATRICES
Let A and B two matrices of the same order. Then their sum, A+B is defined as a matrix, each
element of which is summation of the corresponding elements of A and B. For example, if we have
1 2 3
A = 4 5 6
7 8 9
10 11 12
and
11 22 33
B = 4 55 66
7 88 99
10 11 12
1+11 2+22 3+33
then A + B = 4+4 5+55 6+66
7+7 8+88 9+99
10+10 11+11 12+12
12 24 36
or A +B = 8 60 72
14 96 108
20 22 24
If A = [aij] and B = [bij] then A+B = [aij] + [bij]
The algorithm to find the summation of two matrices is illustrated in Fig. below.
Algorithm to add two matrices
Program to implement above algorithm to add two matrices:
/* Add Tow Matrices */
# include<stdio.h>
# include<stdlib.h>
# define row 10
# define col 10
int i, j;
int row1, col1;
int row2, col2;
float mat1[row][col];
float mat2[row][col];
float mat_res[row][col];
void mat_add( float mat1[row][col], int, int,
float mat2[row][col], int, int,
float mat_res[row][col]);
void display(float mat[row][col], int, int);
void input(float mat[row][col], int , int);
/* Function mat_add */
void mat_add(float mat1[row][col], int row1, int col1,
float mat2[row][col], int row2, int col2,
float mat_res[row][col])
{
int i, j;
if((row1 == row2) && (col1 == col2))
{
printf("\n Addition is possible and Result is as follows\n");
for(i = 0; i<row1; i++)
for(j = 0; j<col1; j++)
mat_res[i][j] = mat1[i][j]+mat2[i][j];
display(mat_res,row1,col1);
}
else
printf("\n Addition is not possible");
exit(0);
}
/* Output function */
void display(float mat[row][col], int r, int c )
{
for(i = 0; i < r; i++)
{
for(j = 0; j < c; j++)
{
printf(" %f", mat[i][j]);
}
printf("\n");
}
}
/* Input function */
void input(float mat[row][col], int r, int c)
{
for( i = 0 ; i < r; i++)
{
for(j = 0 ; j < c; j++)
{
printf("Input Value for : %d: %d: ", i+1, j+1);
scanf("%f", &mat[i][j]);
}
}
}
/* main function */
void main()
{
int row1, col1;
int row2, col2;
float mat1[row][col];
float mat2[row][col];
float mat_res[row][col];
printf("\n Input the row of the matrix->1:");
scanf("%d", &row1);
printf(" Input the col of the matrix->1:");
scanf("%d", &col1);
printf("\n Input data for matrix-> 1\n");
input(mat1, row1, col1);
printf("\n Input the row of the matrix ->2:");
scanf("%d", &row2);
printf("\n Input the col of the matrix->2:");
scanf("%d", &col2);
printf("\n Input data for matrix-> 2\n");
input(mat2, row2, col2);
printf("\n Entered Matrix First is as follows:\n");
display(mat1,row1,col1);
printf("\n Entered Matrix Two is as follows:\n");
display(mat2,row2,col2);
mat_add(mat1, row1, col1, mat2, row2, col2, mat_res);
}
SUBTRACTION OF MATRICES
The difference of two matrices is a matrix, each element of which is obtained by subtracting the
elements of the second matrix from the corresponding element of the first matrix. If A and B are
two matrices then the difference of B and A is noted by B - A will be defined by:
B - A = [bij - aij]
For example, if
11 12 3
A = 41 15 6
71 8 19
10 11 12
and
1 22 33
B = 4 55 6
7 88 9
100 11 12
11-11 22-12 33-3
then B-A = 4-41 55-15 6-6
7-71 88-8 9-19
100-10 11-11 12-12
0 10 30
B-A = -37 40 0
-64 80 -10
90 0 0
Algorithm to Subtract two matrices
Program to implement above algorithm
/* Subtraction of two Matrices */
# include<stdio.h>
# include<stdlib.h>
# define row 10
# define col 10
int i, j;
int row1, col1;
int row2, col2;
float mat1[row][col];
float mat2[row][col];
float mat_res[row][col];
void mat_sub( float mat1[row][col], int, int,
float mat2[row][col], int, int,
float mat_res[row][col]);
void display(float mat[row][col], int, int);
void input(float mat[row][col], int , int);
/* Function mat_sub */
void mat_sub(float mat1[row][col], int row1, int col1,
float mat2[row][col], int row2, int col2,
float mat_res[row][col])
{
if(( row1 == row2) && (col1 == col2))
{
printf("\n Subtraction is possible and Result is as follows\n");
for(i = 0; i < row1; i++)
for(j = 0; j < col1; j++)
mat_res[i][j] = mat1[i][j] - mat2[i][j];
display(mat_res,row1,col1);
}
else
printf("\n Subtraction is not possible");
exit(0);
}
/* Output Function */
void display(float mat[row][col], int r, int c )
{
for(i = 0; i < r; i++)
{
for(j = 0; j < c; j++)
{
printf(" %f", mat[i][j]);
}
printf("\n");
}
}
/* Input function */
void input(float mat[row][col], int r, int c)
{
for(i = 0 ; i< r; i++)
{
for(j = 0 ; j<c; j++)
{
printf("Input Value for : %d: %d: ", i+1, j+1);
scanf("%f", &mat[i][j]);
}
}
}
/* main function */
void main()
{
int row1, col1;
int row2, col2;
float mat1[row][col];
float mat2[row][col];
float mat_res[row][col];
printf("\n Input the row of the matrix->1:");
scanf("%d", &row1);
printf("\n Input the col of the matrix->1:");
scanf("%d", &col1);
printf(" Input data for matrix-> 1\n");
input(mat1, row1, col1);
printf("Input the row of the matrix ->2:");
scanf("%d", &row2);
printf(" Input the col of the matrix->2:");
scanf("%d", &col2);
printf(" Input data for matrix-> 2\n");
input(mat2, row2, col2);
printf("\n Entered Matrix First is as follows:\n");
display(mat1,row1,col1);
printf("\n Entered Matrix Two is as follows:\n");
display(mat2,row2,col2);
mat_sub(mat1,row1,col1,mat2,row1,col2,mat_res);
display(mat_res,row2,col2);
}
MULTIPLICATION OF TWO MATRICES
The product of two matrices A and B is possible if the numbers of columns in A is equal to the
number of rows in B or number of rows in A is equal to the number of columns in B. Let A = [aij]
be an m x n matrix and p matrix. Then the productB = [bij] be an n p say C = [cij]. WhereA.B
of these matrices is of the order of m
cij = ail . blj + ai2 . b2j + + ain . bnj
n
aik . bkj-cij =
k = 1
1 -2 3
A = 2 3 -1
-3 1 2
1 0 2
B = 0 1 2
1 2 0
Multiplying row of 1st matrix and column of 2nd matrix
1*1+(-2)*0+3*1 1*0+(-2)*1+3*2 1*2+(-2)*2+3*0
A. B = 2*1+3*0+(-1)*1 2*0+3*1+(-1)*2 2*2+3*2+(-1)*0
(-3)*1+1*0+2*1 (-3)*0+1*1+2*2 (-3)*2+1*2+2*0
1-0+3 0-2+6 2-4+0
A. B = 2+0-1 0+3-2 4+6-0
-3+0+2 -0+1+4 -6+2+0
4 4 -2
A.B = 1 1 10
-1 5 -4
Algorithm to multiply two matrices
Program to implement above algorithm to multiply two matrices
/* Multiply Two Matrices */
/* MULT_MAT.C */
# include<stdio.h>
# include<stdlib.h>
# define row 10
# define col 10
int i, j;
int row1, col1;
int row2, col2;
float mat1[row][col];
float mat2[row][col];
float mat_res[row][col];
void mat_mult( float mat1[row][col], int, int,
float mat2[row][col], int, int,
float mat_res[row][col]);
void display(float mat[row][col], int, int);
void input(float mat[row][col], int , int);
/* function to multiply two matrices */
void mat_mult( float mat1[row][col], int row1, int col1,
float mat2[row][col], int row2, int col2,
float mat_res[row][col])
{
int i, j, k;
if(col1 == row2)
{
printf("\n Multiplication is possible and Result is as follows\n");
for(i =0; i<row1; i++)
for(j=0; j<col2; j++)
{
mat_res[i][j] = 0;
for(k = 0; k < col1; k ++)
{
mat_res[i][j] += mat1[i][k] * mat2[k][j];
}
}
display(mat_res, row1, col2);
}
else
printf("\n Multiplication is not possible");
exit(0);
}
/* Output function */
void display(float mat[row][col], int r, int c )
{
for( i = 0; i < r; i++)
{
for( j = 0; j < c; j++)
{
printf(" %f", mat[i][j]);
}
printf("\n");
}
}
/* Input function */
void input(float mat[row][col], int r, int c)
{
for( i = 0 ; i< r; i++)
{
for( j = 0 ; j<c; j++)
{
printf("Input Value for : %d: %d: ", i+1, j+1);
scanf("%f", &mat[i][j]);
}
}
}
/* main function */
void main()
{
int row1, col1;
int row2, col2;
float mat1[row][col];
float mat2[row][col];
float mat_res[row][col];
printf("\n Input the row of the matrix->1:");
scanf("%d", &row1);
printf("\n Input the col of the matrix->1:");
scanf("%d", &col1);
printf("\n Input data for matrix-> 1\n");
input(mat1, row1, col1);
printf("\n Input the row of the matrix ->2:");
scanf("%d", &row2);
printf("\n Input the col of the matrix->2:");
scanf("%d", &col2);
printf("\n Input data for matrix-> 2\n");
input(mat2, row2, col2);
printf("\n Entered Matrix First is as follows:\n");
display(mat1,row1,col1);
printf("\n Entered Matrix Two is as follows:\n");
display(mat2,row2,col2);
mat_mult(mat1 ,row1 ,col1, mat2, row2, col2, mat_res);
}
TRANSPOSE OF A MATRIX
A transpose of a matrix is obtained by interchanging the rows with corresponding columns of a
given matrix. A transpose of matrix A generally n then after transposingis denoted by AT. If
matrix A is an m it we will get m matrix AT. If A = [aij] then AT = [aji].an n
For example :
1 2 3 4
A = 5 6 7 8
9 10 11 12
Then transpose of A is:
1 5 9
2 6 10
A^T = 3 7 11
4 8 12
Algorithm to transpose a matrix
Program to transpose a matrix
/* Transpose of a matrix */
# include<stdio.h>
int i, j;
int value;
int mat[10][10];
void display(int, int);
void display_o( int transp[10][10],int, int);
void input( int transp[10][10],int, int);
void transpose( int transp[10][10],int, int);
/* Transpose function */
void transpose(int transp[10][10], int row, int col)
{
for(i = 0; i< row; i++)
{
for(j = 0; j < col; j++)
{
mat[i][j] = transp[j][i] ;
}
}
}
/* Output function */
void display(int row, int col)
{
for(i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
{
printf(" %d", mat[i][j]);
}
printf("\n");
}
}
/* Output function */
void display_o(int transp[10][10], int row, int col)
{
for(i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
{
printf(" %d", transp[i][j]);
}
printf("\n");
}
}
/* Input function */
void input(int transp[10][10], int row, int col)
{
for(i = 0 ; i< row; i++)
{
for(j = 0 ; j<col; j++)
{
printf("Input Value for : %d: %d: ", i+1,j+1);
scanf("%d", &value);
transp[i][j] = value;
}
}
}
/* main function */
void main()
{
int row,col;
int transp[10][10];
printf("\n Input the number of rows:");
scanf("%d", &row);
printf(" Input number of cols:");
scanf("%d", &col);
input(transp, row, col);
printf("\n Entered Matrix is as follows:\n");
display_o(transp, row, col);
transpose(transp,col,row);
printf("\n Transpose of above matrix is as follows:\n");
display(col, row);
}
INVERSE OF A MATRIX
If A and B are two matrices of the same order such that
A.B = B.A = U[ Where U is a unity matrix]
Then B is called the inverse of A and is denoted as B = A-1 , to Possesses an inverse of matrix A ,
the matrix should be a nonsingular:
0- | A |
If A is a matrix and B be its inverse, then A.B = U
Taking determinant of both sides
| A.B | = | U |
| A |.| B | = | U |
|-From this relation it is clear that |A| U | that is matrix A is non-Singular . There are two
techniques to find inverse of matrix. Inverse of matrix with the help of adjoin matrix that is
A . (Adjoin A) = |A| . U
A . (Adjoin A) = |A| . U
Or A . 1 . (Adjoin A) = U
| A |

and A . A-1 = U
that is
A-1 = 1 . (Adjoin A)
| A |
(ii) Inverse of a matrix from elementary matrices
If A is reduced to U by elementary row transformation then E . A =U
Where E = En En-1.E2E1
Then E = A-1 = Elementary matrix.
Algorithm for inverse of a matrix
Program to implement the given algorithm for inverse of a matrix
/* Find Inverse of a Matrix */
# include<stdio.h>
int i, j;
void display( int, int, float mat[10][10],float mat1[10][10]);
void input( int, int, float mat[10][10],float mat1[10][10]);
Inverse_Mat(int , int, float mat[10][10],float mat1[10][10]);
void swap(int, int, int, float mat[10][10],float mat1[10][10]);
/* This function exchange two rows of a matrix */
void swap( int row1,int row2, int col, float mat[10][10],float mat1[10][10])
{
for( i = 0; i < col; i++)
{
float temp = mat[row1][i];
mat[row1][i] = mat[row2][i];
mat[row2][i] = temp;
temp = mat1[row1][i];
mat1[row1][i] = mat1[row2][i];
mat1[row2][i] = temp;
}
}
/* This function find inverse of matrix */
int Inverse_Mat(int row1, int col1, float mat[10][10],float mat1[10][10])
{
int singular = 0;
int r, c;
for(r = 0;( r < row1)&& !singular; r++)
{
if( mat[r][r] ) /* Diagonal element is not zero */
for(c = 0; c < col1; c++)
if( c == r)
{
/* Make all the elements above and below the current principal diagonal element zero */
float ratio = mat[r][r];
for( i = 0; i < col1; i++)
{
mat[r][i] /= ratio ;
mat1[r][i] /= ratio;
}
}
else
{
float ratio = mat[c][r] / mat[r][r];
for( i = 0; i < col1; i++)
{
mat[c][i] -= ratio * mat[r][i];
mat1[c][i] -= ratio * mat1[r][i];
}
}
else
{
/* If principal diagonal element is zero */
singular = 1;
for(c = (r+1); (c < col1) && singular; ++c)
if(mat[c][r])
{
singular = 0;
/* Find non zero elements in the same column */
swap(r,c,col1, mat, mat1);
--r;
}
}
}
return(!singular);
}
/* To print output this is used */
void display( int row, int col, float mat[10][10],float mat1[10][10])
{
printf("\n");
/* Output of inverse Matrix */
for( i = 0; i < row; i++)
{
for( j = 0; j < col; j++)
{
printf(" %f", mat1[i][j]);
}
printf("\n");
}
}
/* input function */
void input( int row, int col, float mat[10][10],float mat1[10][10])
{
for( i = 0 ; i< row; i++)
{
for( j = 0 ; j<col; j++)
{
printf("Input Value for: %d: %d: ", i+1, j+1);
scanf("%f", &mat[i][j]);
mat1[i][j] = 0;
}
mat1[i][i] = 1;
}
printf("\n Entered Matrix is as follows:\n");
for( i = 0; i < row; i++)
{
for( j = 0; j < col; j++)
{
printf(" %f", mat[i][j]);
}
printf("\n");
}
}
/* main function */
void main()
{
int R, C;
float mat[10][10];
float mat1[10][10];
printf("\n Input number of rows:");
scanf("%d", &R);
printf(" Input number of cols:");
scanf("%d", &C);
input(R,C, mat, mat1);
Inverse_Mat(R,C, mat, mat1);
printf("\n Inverse of above matrix is as follows:\n ");
display(R,C, mat, mat1);
}
RANK OF A MATRIX
The rank of a matrix r is defined if It has at least one non-zero minor of order r.Every minor of
order higher than r is zero.
To find the rank of matrix reduce the given matrix to upper triangular form. Rank of the matrix is
equal to the number of non-zero roes. A non-zero must contain at least one non-zero number.
For example:-
1 4 5
A = 2 6 8
3 7 22
Step 1 : Subtract 2 times of the first row from the second row that is
R2 - 2*R1 and 3 times of the first row from the third row that is R3 -3*R1.
1 4 5
0 -2 -2
0 -5 7
Taking -2 common from the second row we get
1 4 5
0 1 1 -1/2R2
0 -5 7
Adding 5 times the second row into the third row that is R3 + 5*R2
1 4 5
0 1 1
0 0 12
Thus from the above resulting matrix it is clear that there is no non - zero row in the matrix hence
the rank of the matrix A is 3.
The algorithm to find rank of a matrix is given below:
Algorithm to find rank of a matrix
Program to implement above algorithm to find the rank of a matrix
/* Find Rank of a Matrix */
# include<stdio.h>
int R,C;
int i, j;
int mat[10][10];
void display( int, int);
void input( int, int);
int Rank_Mat(int , int);
void swap(int, int, int);
/* This function exchange two rows of a matrix */
void swap( int row1,int row2, int col)
{
for( i = 0; i < col; i++)
{
int temp = mat[row1][i];
mat[row1][i] = mat[row2][i];
mat[row2][i] = temp;
}
}
/* This function find rank of matrix */
int Rank_Mat(int row1, int col1)
{
int r, c;
for(r = 0; r< col1; r++)
{
display(R,C);
if( mat[r][r] ) // Diagonal element is not zero
for(c = 0; c < row1; c++)
if(c != r)
{
/* Make all the elements above and below the current principal diagonal element zero */
float ratio = mat[c][r]/ mat[r][r];
for( i = 0; i < col1; i++)
mat[c][i] -= ratio * mat[r][i];
}
else
printf("\n");
/* Principal Diagonal elment is zero */
else
{
for(c = r+1 ; c < row1; c++)
if (mat[c][r])
{
/* Find non zero elements in the same column */
swap(r,c,col1);
break ;
}
if(c == row1)
{
-- col1;
for(c = 0; c < row1; c ++)
mat[c][r] = mat[c][col1];
}
--r;
}
}
return col1;
}
/* Output function */
void display( int row, int col)
{
for(i = 0; i < row; i++)
{
for(j = 0; j < col; j++)
{
printf(" %d", mat[i][j]);
}
printf("\n");
}
}
/* Input function */
void input( int row, int col)
{
int value;
for(i = 0 ; i< row; i++)
{
for(j = 0 ; j<col; j++)
{
printf("Input Value for: %d: %d: ", i+1, j+1);
scanf("%d", &value);
mat[i][j] = value;
}
}
}
/* main function */
void main()
{
int rank;
printf("\n Input number of rows:");
scanf("%d", &R);
printf("\n Input number of cols:");
scanf("%d", &C);
input(R, C);
printf("\n Row is : %d", R);
printf("\n Column is : %d \n", C);
printf("\n Entered Two Dimensional array is as follows:\n");
display(R,C);
printf("\n Row is : %d", R);
printf("\n Column is : %d\n", C);
rank = Rank_Mat(R, C);
printf("\n Rank of above matrix is : %d", rank);
}
GENERAL MULTIDIMENSIONAL ARRAYS
General multidimensional arrays can be defined by analogously.
Program to illustrate a 9 subscript array:
# include<stdio.h>
# define r 2
void main()
{
int m[r][r][r][r][r][r][r][r][r];
int a, b, c, d, e, f, g, h, i;
/* Input section */
for (a = 0; a < r; a++)
for (b = 0; b < r; b++)
for (c = 0; c < r; c++)
for (d = 0; d < r; d++)
for (e = 0; e < r; e++)
for (f = 0; f < r; f++)
for (g = 0; g < r; g++)
for (h = 0; h < r; h++)
for (i = 0; i < r; i++)
m[a][b][c][d][e][f][g][h][i] = a+b+c+d+e+f+g+h+i;
/* Output section row major order */
printf("\n ADDRESS ARRAY M WITH INDEX VALUE \n");
for (a = 0; a < r; a++)
for (b = 0; b < r; b++)
for (c = 0; c < r; c++)
for (d = 0; d < r; d++)
for (e = 0; e < r; e++)
for (f = 0; f < r; f++)
for (g = 0; g < r; g++)
for (h = 0; h < r; h++)
for (i = 0; i < r; i++)
{
printf("\n 0x%x", &m[a][b][c][d][e][f][g][h][i]);
printf(" m[%d][%d][%d][%d][%d][%d][%d][%d][%d] = %d",a,
b, c, d, e, f, g, h, i, m[a][b][c][d][e][f][g][h][i]);
}
/* Column major order */
printf("\n ADDRESS ARRAY M WITH INDEX VALUE \n");
\
for (i = 0; i < r; i++)
for (h = 0; h < r; h++)
for (g = 0; g < r; g++)
for (f = 0; f < r; f++)
for (e = 0; e < r; e++)
for (d = 0; d < r; d++)
for (c = 0; c < r; c++)
for (b = 0; b < r; b++)
for (a = 0; a < r; a++)
{
printf("\n 0x%x", &m[a][b][c][d][e][f][g][h][i]);
printf(" m[%d][%d][%d][%d][%d][%d][%d][%d][%d] = %d",a, b, c, d, e, f, g, h, i, m[a][b][c]
[d][e][f][g][h][i]);
}
}
LINKED LIST
In this section we will discuss linear data structures linked list. The computers are used in data
processing to perform operations like:
Deletion of_ information
Insertion of information_
Updating_ information
Report writing etc._
If we use fixed length memory storage (arrays) it is not always possible to perform above tasks. A
linked list allocation storage method can result in efficient use of computer memory and computer
time. Linked list are useful because:
Unpredictable storage requirements: The exact amount of data storage space required by a
program in these areas often depends on the data begin processed and consequently this
requirement can not be easily determined at the time of writing the program.
Extensive manipulation of the stored data: Program in these areas requires the operations such as
insertion and deletion to perform frequent operations on the data.
A linked list is defined as a collection of nodes. Each node has two parts:
Information
TREES
INTRODUCTION
A tree structure means that the data is organized as branches, which relate the information, one
field where such structure is commonly used in the investigation of genealogies.
LINEAGE CHART
The lineage chart represents ancestors and in this example Mc dowel has two children Scot and
Leacha. Don and Mac are children of Scot and Scot is son of Mc dowel thus we can say that Mc
dowel is the grand father of Don and Mac. Thus as we go further we find that this lineage chart is
useful is the investigation of family history called genealogies.
A tree T is defined as a finite set of one or more nodes such that
There is a special node called the root R._
0 disjoint sets T1, T2, .Tn, The remaining nodes are divided into n _ Where each of
these
sets is a tree. T1, T2, .Tn is called the sub-tree of the root.
In other words one may define a tree as a collection of nodes and each node is linked with another
node with the help of a branch. The nodes are connected in such a way that there are no loops and
there is a special node called root.
Each node in a tree is assigned a level number as follows The root node R of the tree is assigned
a level number 0, and a node is assigned a level number, which is one more than the level number
of its parent(Root) of the sub-tree to which it belongs. The nodes, which are at the same level
numbers, are said to be of the same generation. The height or depth of a tree is the maximum
number of nodes in a branch. This turns out to be one more than the largest level number of the
tree.
BINARY TREE
A binary tree is an important type of data structure, which is very useful. A tree is binary tree if
each node of it have at most two branches . In other words we can say that if every node of a tree
can have at most degree two, then this is called a binary tree. In a binary tree left and right sub-
trees distinguish sub-trees of a node.
A binary tree T is a finite set of nodes, which is either empty or consists of special node called root
R and two disjoint binary trees T1 and T2 (which are called the left sub-tree and right sub-trees,
respectively). If T1 is non-empty then the root of T1 is called the left successor of R. If T2 is non-
empty then the root of T2 is known as right successor of R.
Binary tree --- T
Left sub-tree of the Binary tree T
Right sub-tree of the binary tree T
Algorithm to create Binary tree
/* Program To Create Binary TREE */
# include<stdio.h>
# include<malloc.h>
struct NODE
{
int Info;
struct NODE *Left_Child;
struct NODE *Right_Child;
};
struct NODE *Binary_Tree (char *, int, int);
void Output(struct NODE *, int );
/* Function to insert an element into tree */
struct NODE * Binary_Tree (char *List, int Lower, int Upper)
{
struct NODE *Node;
int Mid = (Lower + Upper)/2;
Node = (struct NODE *) malloc(sizeof(struct NODE));
Node->Info = List [Mid];
if ( Lower>= Upper)
{
Node->Left_Child = NULL;
Node->Right_Child = NULL;
return (Node);
}
if (Lower <= Mid - 1)
Node->Left_Child = Binary_Tree (List, Lower, Mid - 1);
else
Node->Left_Child = NULL;
if (Mid + 1 <= Upper)
Node->Right_Child = Binary_Tree (List, Mid + 1, Upper);
else
Node->Right_Child = NULL;
return(Node);
}
/* Output function */
void Output(struct NODE *T, int Level)
{
int i;
if (T)
{
Output(T->Right_Child, Level+1);
printf("\n");
for (i = 0; i < Level; i++)
printf(" ");
printf("%c", T->Info);
Output(T->Left_Child, Level+1);
}
}
/* Function main */
void main()
{
char List[100];
int Number = 0;
char Info ;
char choice;
struct NODE *T = (struct NODE *) malloc(sizeof(struct
NODE));
T = NULL;
printf("\n Input choice 'b' to break:");
choice = getchar();
while(choice != 'b')
{
printf("\n Input information of the node: ");
scanf("%c", &Info);
List[Number++] = Info;
fflush(stdin);
printf("\n Input choice 'b' to break:");
choice = getchar();
}
Number --;
printf("\n Number of elements in the lsit is %d", Number);
T = Binary_Tree(List, 0, Number);
Output(T,1);
}

COMPLETE BINARY TREE
A binary tree T is called complete if each node of t can have at most two children. A binary tree T
at level L can have at most 2L nodes. For example:
If L = 0, then 20 = 1 implies that there is only one node in the tree that is a root.
If L = 1, then 21 = 2 implies that there are only two nodes in the tree at level 1 a left and right
successor of root.
If L = 2, then 22 = 4 implies that there are only four nodes in the tree at level 2 and so on.
Complete Binary Tree
If we assume that v1 = 1 is a root and its left sub-trees root is v2 = 2*v1 = 2*1 = 2 and right
sub-trees root is v3 = 2*v1 + 1 = 2*1 + 1 = 3 and we consider the 4th nodes its value is 4 then
its left sub-tree value is = 4*2 = 8, and right sub-trees value is 4*2 + 1 = 9 and so on. If we
consider node v then its left child will be at position 2*v and right will be at position 2*v + 1.
Thus the depth of the binary tree with n nodes is given by
Dn =[ Log 2 n+1]
/* Finding Depth of Binary Tree */
/* DEPTH_BT.C */
# include<stdio.h>
# include<malloc.h>
struct NODE
{
char Info;
struct NODE *Left_Child;
struct NODE *Right_Child;
};
int depth = 0;
void Output (struct NODE *, int );
int Depth (struct NODE *, int );
struct NODE *Create_Tree (char , struct NODE *);
/* Output function */
void Output(struct NODE *T, int Level)
{
int i;
if (T)
{
Output(T->Right_Child, Level+1);
printf("\n");
for (i = 0; i < Level; i++)
printf(" ");
printf("%c", T->Info);
Output(T->Left_Child, Level+1);
}
}
/* Find depth of the tree */
int Depth (struct NODE *Node, int Level)
{
if (Node != NULL)
{
if (Level > depth)
depth = Level;
Depth (Node->Left_Child, Level + 1);
Depth (Node->Right_Child, Level + 1);
}
return (depth);
}
/* Create binary tree */
struct NODE * Create_Tree (char Info, struct NODE *Node)
{
if (Node == NULL)
{
Node = (struct NODE *) malloc(sizeof(struct NODE));
Node->Info = Info;
Node->Left_Child = NULL;
Node->Right_Child = NULL;
return (Node);
}
/* Test for the left child */
if (Info < Node->Info)
Node->Left_Child = Create_Tree (Info, Node->Left_Child);
else
/* Test for the right child */
if (Info > Node->Info)
Node->Right_Child = Create_Tree (Info, Node->Right_Child);
return(Node);
}
/* Function main */
void main()
{
int Number = 0;
char Info ;
char choice;
int depth;
struct NODE *T = (struct NODE *) malloc(sizeof(struct NODE));
T = NULL;
printf("\n Input choice 'b' to break:");
choice = getchar();
while(choice != 'b')
{
fflush(stdin);
printf("\n Input information of the node: ");
scanf("%c", &Info);
T = Create_Tree(Info, T);
Number++;
fflush(stdin);
printf("\n Input choice 'b' to break:");
choice = getchar();
}
printf("\n Number of elements in the list is %d", Number);
printf("\n Tree is \n");
Output(T, 1);
depth = Depth(T, 0);
printf("\n Depth of the above tree is: %d", depth);
}
REPRESENTATION OF BINARY TREE
There are two traditional popular techniques that are used to maintain binary tree in the memory.
These are :
Sequential_ representation.
Linked list representation._
SEQUENTIAL REPRESENTATION
A sequential representation of a binary tree requires numbering of nodes; starting with nodes on
level 0, then on level 1, and so on. The node are numbered from left to right. The nodes of the
binary tree are maintained in a one-dimensional array.
Binary Tree -- T

LINKED LIST REPRESENTATION
The problem associated with the sequential representation of binary tree can be overcome through
the use of the linked list representation. In this representation each node requires three fields, one
for the link of the left child, second field for representing the information associated with the node
and the third field is used to represent the link of the right child.
Fig. Binary tree T
TRAVERSING BINARY TREE
Traversing means visiting each node exactly once. A full traversal of a binary tree T produces a
linear order of elements existing in T. There are three basic ways for traversing a binary tree.
PREORDER
In this technique first of all we process the root R of the binary tree T. Then we traverse the left
sub- tree T1 of R in preorder, which means that we traverse root of the sub- tree T1 first and then
its left sub- tree. After traversing left sub- tree of R then we take over right sub- tree of R and
process all the nodes in preorder.
Fig. (A) Binary tree T with 13 nodes
Recursive algorithm of preorder traversing
IN ORDER
In the inorder traversing technique first of all we process the left sub- tree T1 of the root R in the
inorder. Then process the root R and at the last we process the right sub-tree T2 of R.
Recursive algorithm of inorder traversing
POST ORDER
In this technique first of all, we process the left sub-tree T1 of R in postorder, then the right sub-
tree T2 in postorder and at the last the root R.
Recursive algorithm of postorder traversing

SEARCH TREE
A binary search tree is a tree that is either empty or in which each node possesses a key that
satisfies the following conditions:
(i) All keys (if any) in the left sub-tree of the root precede the key in the root.
(ii) The key in the root precedes all keys (if any) in its right sub-tree.
(iii) The left and right sub-trees of the root are again search trees.
Binary search algorithm
/* Searching Binary Tree */
/* SEARCH_B.C */
# include<stdio.h>
# include<malloc.h>
struct NODE
{
char Info;
struct NODE *Left_Child;
struct NODE *Right_Child;
};
int flag = 0;
struct NODE *Binary_Tree (char *, int, int);
void Output(struct NODE *, int );
int Search_Node(struct NODE *, char);
/* Function to create an binary tree */
struct NODE * Binary_Tree (char *List, int Lower, int Upper)
{
struct NODE *Node;
int Mid = (Lower + Upper)/2;
Node = (struct NODE*) malloc(sizeof(struct NODE));
Node->Info = List [Mid];
if ( Lower>= Upper)
{
Node->Left_Child = NULL;
Node->Right_Child = NULL;
return (Node);
}
if (Lower <= Mid - 1)
Node->Left_Child = Binary_Tree (List, Lower, Mid - 1);
else
Node->Left_Child = NULL;
if (Mid + 1 <= Upper)
Node->Right_Child = Binary_Tree (List, Mid + 1, Upper);
else
Node->Right_Child = NULL;
return(Node);
}
/* Output function */
void Output(struct NODE *T, int Level)
{
int i;
if (T)
{
Output(T->Right_Child, Level+1);
printf("\n");
for (i = 0; i < Level; i++)
printf(" ");
printf("%c", T->Info);
Output(T->Left_Child, Level+1);
}
}
/* Insert a node in the tree */
int Search_Node(struct NODE *Node, char Info)
{
while (Node != NULL)
{
if (Node->Info == Info)
{
flag = 1;
return(flag);
}
else
if(Info < Node->Info)
{
Node = Node->Left_Child;
}
else
{
Node = Node->Right_Child;
}
}
return(flag);
}
/* Function main */
void main()
{
int flag;
char List[100];
int Number = 0;
char Info ;
char choice;
struct NODE *T = (struct NODE *) malloc(sizeof(struct NODE));
T = NULL;
printf("\n Input choice 'b' to break:");
choice = getchar();
while(choice != 'b')
{
fflush(stdin);
printf("\n Input information of the node: ");
scanf("%c", &Info);
List[Number++] = Info;
fflush(stdin);
printf("\n Input choice 'b' to break:");
choice = getchar();
}
Number --;
printf("\n Number of elements in the list is %d", Number+1);
T = Binary_Tree(List, 0, Number);
printf("\n Tree is \n");
Output(T, 1);
fflush(stdin);
printf("\n Input the information of the node to which want to search: ");
scanf("%c", &Info);
flag = Search_Node(T, Info);
if (flag)
{
printf("\n Search is successful \n");
}
else
printf("Search unsuccessful");
}

DELETION IN A BINARY TREE
The deletion is an easy task if the deleted node has only one sub-tree. In this case we simply link
the parent of the deleted node to its sub-tree. When the element to be deleted has both left and
right sub-trees nonempty, the problem becomes more complicate.
Deletion in binary search tree phase 1

Deletion in binary search tree phase 2
Deletion in Binary search tree
/* Deleting in Binary Tree */
# include<stdio.h>
# include<malloc.h>
struct NODE
{
int Info;
struct NODE *Left_Child;
struct NODE *Right_Child;
};
int depth;
void Output (struct NODE *, int );
struct NODE *Delet_Node (struct NODE *, int );
struct NODE *Create_Tree (int , struct NODE *);
struct NODE * DELE(struct NODE *, struct NODE *);
/* Output function */
void Output(struct NODE *T, int Level)
{
int i;
if (T)
{
Output(T->Right_Child, Level+1);
printf("\n");
for (i = 0; i < Level; i++)
printf(" ");
printf("%c", T->Info);
Output(T->Left_Child, Level+1);
}
}
/* Delete a node in the binary tree */
struct NODE * DELE(struct NODE *Node1, struct NODE *Node)
{
struct NODE *DNode;
if (Node1->Right_Child != NULL)
Node1->Right_Child = DELE(Node1->Right_Child, Node);
else
{
DNode = Node1;
Node->Info = Node1->Info;
Node1 = Node1->Left_Child;
free(DNode);
}
return (Node1);
}
/* Deletion in binary tree */
struct NODE * Delet_Node (struct NODE *Node, int Info)
{
struct NODE *Temp;
if (Node == NULL)
{
printf("\n Information does not exist in the above tree");
return (Node);
}
else
{
if (Info < Node->Info )
Node->Left_Child = Delet_Node (Node->Left_Child, Info);
else
if (Info > Node->Info )
Node->Left_Child = Delet_Node (Node->Right_Child, Info);
else
{
Temp = Node;
if (Temp->Right_Child == NULL)
{
Node = Temp->Left_Child;
free(Temp);
}
else
if (Temp->Left_Child == NULL)
{
Node = Temp->Right_Child;
free(Temp);
}
else
Temp->Left_Child = DELE(Temp->Left_Child, Temp);
}
}
return(Node);
}
/* Create binary tree */
struct NODE * Create_Tree (int Info, struct NODE *Node)
{
if (Node == NULL)
{
Node = (struct NODE *) malloc(sizeof(struct NODE));
Node->Info = Info;
Node->Left_Child = NULL;
Node->Right_Child = NULL;
return (Node);
}
/* Test for the left child */
if (Info < Node->Info)
Node->Left_Child = Create_Tree (Info, Node->Left_Child);
else
/* Test for the right child */
if (Info >= Node->Info)
Node->Right_Child = Create_Tree (Info, Node->Right_Child);
return(Node);
}
/* Function main */
void main()
{
int Number = 0;
int Info ;
char choice;
int depth;
struct NODE *T = (struct NODE *) malloc(sizeof(struct NODE));
T = NULL;
printf("\n Input choice 'b' to break:");
choice = getchar();
while(choice != 'b')
{
fflush(stdin);
printf("\n Input information of the node: ");
scanf("%c", &Info);
T = Create_Tree(Info, T);
Number++;
fflush(stdin);
printf("\n Input choice 'b' to break:");
choice = getchar();
}
fflush(stdin);
printf("\n Number of elements in the list is %d", Number);
printf("\n Tree is \n");
Output(T, 1);
printf("\n Input the information to which want remove from the above tree: ");
scanf("%c", &Info);
T = Delet_Node(T, Info);
printf("\n Tree after deletion of a node: ");
Output(T, 1);
}
AVL TREE
A tree is called AVL tree (Balanced binary tree), if each node possesses one of the following
properties:
A node is called left heavy, if the longest path in its left sub-tree is one longer than the longest
path of its right sub-tree.
A node is called right heavy, if the longest path in its right sub-tree is one longer than the longest
path of its left sub-tree.
A node is called balanced, if the longest paths in both the right and left sub-trees are equal.
A Balanced Binary tree
Insertion Algorithm for AVL tree
/* Create AVL Binary TREE */
/* AVL_TREE.C */
# include<stdio.h>
# include<malloc.h>
# define F 0
# define T 1
struct NODE
{
char Info;
int Flag;
struct NODE *Left_Child;
struct NODE *Right_Child;
};
struct NODE *Binary_Tree (char , struct NODE *, int *);
void Output(struct NODE *, int );
struct NODE *Balance_Right_Heavy(struct NODE *, int *);
struct NODE *Balance_Left_Heavy(struct NODE *, int *);
struct NODE *DELETE(struct NODE *, struct NODE *, int *);
struct NODE *Delete_Element(struct NODE *, char , int *);
/* Function to insert an element into tree */
struct NODE * Binary_Tree (char Info, struct NODE *Parent, int *H)
{
struct NODE *Node1;
struct NODE *Node2;
if(!Parent)
{
Parent = (struct NODE *) malloc(sizeof(struct NODE));
Parent->Info = Info;
Parent->Left_Child = NULL;
Parent->Right_Child = NULL;
Parent->Flag = 0;
*H = T;
return (Parent);
}
if(Info < Parent->Info)
{
Parent->Left_Child = Binary_Tree(Info, Parent->Left_Child, H);
if(*H)
/* Left branch has grown higher */
{
switch(Parent->Flag)
{
case 1: /* Right heavy */
Parent->Flag = 0;
*H = F;
break;
case 0: /* Balanced tree */
Parent->Flag = -1;
break;
case -1: /* Left heavy */
Node1 = Parent->Left_Child;
if(Node1->Flag == -1)
{
printf("\n Left to Left Rotation\n");
Parent->Left_Child= Node1->Right_Child;
Node1->Right_Child = Parent;
Parent->Flag = 0;
Parent = Node1;
}
else
{
printf("\n Left to right rotation\n");
Node2 = Node1->Right_Child;
Node1->Right_Child = Node2->Left_Child;
Node2->Left_Child = Node1;
Parent->Left_Child = Node2->Right_Child;
Node2->Right_Child = Parent;
if(Node2->Flag == -1)
Parent->Flag = 1;
else
Parent->Flag = 0;
if(Node2->Flag == 1)
Node1->Flag = -1;
else
Node1->Flag = 0;
Parent = Node2;
}
Parent->Flag = 0;
*H = F;
}
}
}
if(Info > Parent->Info)
{
Parent->Right_Child = Binary_Tree(Info, Parent->Right_Child, H);
if(*H)
/* Right branch has grown higher */
{
switch(Parent->Flag)
{
case -1: /* Left heavy */
Parent->Flag = 0;
*H = F;
break;
case 0: /* Balanced tree */
Parent->Flag = 1;
break;
case 1: /* Right heavy */
Node1 = Parent->Right_Child;
if(Node1->Flag == 1)
{
printf("\n Right to Right Rotation\n");
Parent->Right_Child= Node1->Left_Child;
Node1->Left_Child = Parent;
Parent->Flag = 0;
Parent = Node1;
}
else
{
printf("\n Right to Left Rotation\n");
Node2 = Node1->Left_Child;
Node1->Left_Child = Node2->Right_Child;
Node2->Right_Child = Node1;
Parent->Right_Child = Node2->Left_Child;
Node2->Left_Child = Parent;
if(Node2->Flag == 1)
Parent->Flag = -1;
else
Parent->Flag = 0;
if(Node2->Flag == -1)
Node1->Flag = 1;
else
Node1->Flag = 0;
Parent = Node2;
}
Parent->Flag = 0;
*H = F;
}
}
}
return(Parent);
}
/* Output function */
void Output(struct NODE *Tree,int Level)
{
int i;
if (Tree)
{
Output(Tree->Right_Child, Level+1);
printf("\n");
for (i = 0; i < Level; i++)
printf(" ");
printf("%c", Tree->Info);
Output(Tree->Left_Child, Level+1);
}
}
/* Balancing Right Heavy */
struct NODE * Balance_Right_Heavy(struct NODE *Parent, int *H)
{
struct NODE *Node1, *Node2;
switch(Parent->Flag)
{
case -1:
Parent->Flag = 0;
break;
case 0:
Parent->Flag = 1;
*H= F;
break;
case 1: /* Rebalance */
Node1 = Parent->Right_Child;
if(Node1->Flag >= 0)
{
printf("\n Right to Right Rotation\n");
Parent->Right_Child= Node1->Left_Child;
Node1->Left_Child = Parent;
if(Node1->Flag == 0)
{
Parent->Flag = 1;
Node1->Flag = -1;
*H = F;
}
else
{
Parent->Flag = Node1->Flag = 0;
}
Parent = Node1;
}
else
{
printf("\n Right to Left Rotation\n");
Node2 = Node1->Left_Child;
Node1->Left_Child = Node2->Right_Child;
Node2->Right_Child = Node1;
Parent->Right_Child = Node2->Left_Child;
Node2->Left_Child = Parent;
if(Node2->Flag == 1)
Parent->Flag = -1;
else
Parent->Flag = 0;
if(Node2->Flag == -1)
Node1->Flag = 1;
else
Node1->Flag = 0;
Parent = Node2;
Node2->Flag = 0;
}
}
return(Parent);
}
/* Balancing Left Heavy */
struct NODE * Balance_Left_Heavy(struct NODE *Parent, int *H)
{
struct NODE *Node1, *Node2;
switch(Parent->Flag)
{
case 1:
Parent->Flag = 0;
break;
case 0:
Parent->Flag = -1;
*H= F;
break;
case -1: /* Rebalance */
Node1 = Parent->Left_Child;
if(Node1->Flag <= 0)
{
printf("\n Left to Left Rotation\n");
Parent->Left_Child= Node1->Right_Child;
Node1->Right_Child = Parent;
if(Node1->Flag == 0)
{
Parent->Flag = -1;
Node1->Flag = 1;
*H = F;
}
else
{
Parent->Flag = Node1->Flag = 0;
}
Parent = Node1;
}
else
{
printf("\n Left to Right Rotation\n");
Node2 = Node1->Right_Child;
Node1->Right_Child = Node2->Left_Child;
Node2->Left_Child = Node1;
Parent->Left_Child = Node2->Right_Child;
Node2->Right_Child = Parent;
if(Node2->Flag == -1)
Parent->Flag = 1;
else
Parent->Flag = 0;
if(Node2->Flag == 1)
Node1->Flag = -1;
else
Node1->Flag = 0;
Parent = Node2;
Node2->Flag = 0;
}
}
return(Parent);
}
/* Replace the node at which key is found with last right key of a left child */
struct NODE * DELETE(struct NODE *R, struct NODE *Temp, int *H)
{
struct NODE *Dnode = R;
if( R->Right_Child != NULL)
{
R->Right_Child = DELETE(R->Right_Child, Temp, H);
if(*H)
R = Balance_Left_Heavy(R, H);
}
else
{
Dnode = R;
Temp->Info = R->Info;
R = R->Left_Child;
free(Dnode);
*H = T;
}
return(R);
}
/* Delete the key element from the tree */
struct NODE * Delete_Element(struct NODE *Parent, char Info, int *H)
{
struct NODE *Temp;
if(!Parent)
{
printf("\n Information does not exist");
return(Parent);
}
else
{
if (Info < Parent->Info )
{
Parent->Left_Child = Delete_Element(Parent->Left_Child,
Info, H);
if(*H)
Parent = Balance_Right_Heavy(Parent, H);
}
else
if(Info > Parent->Info)
{
Parent->Right_Child = Delete_Element(Parent-> Right_Child,
Info, H);
if(*H)
Parent = Balance_Left_Heavy(Parent, H);
}
else
{
Temp= Parent;
if(Temp->Right_Child == NULL)
{
Parent = Temp->Left_Child;
*H = T;
free(Temp);
}
else
if(Temp->Left_Child == NULL)
{
Parent = Temp->Right_Child;
*H = T;
free(Temp);
}
else
{
Temp->Left_Child = DELETE(Temp->Left_Child, Temp, H);
if(*H)
Parent = Balance_Right_Heavy(Parent, H);
}
}
}
return(Parent);
}
/* Function main */
void main()
{
int H;
char Info ;
char choice;
struct NODE *Tree = (struct NODE *)malloc(sizeof(struct NODE));
Tree = NULL;
printf("\n Input choice 'b' to break:");
choice = getchar();
while(choice != 'b')
{
fflush(stdin);
printf("\n Input information of the node: ");
scanf("%c", &Info);
Tree = Binary_Tree(Info, Tree, &H);
printf("\n Tree is:\n");
Output(Tree, 1);
fflush(stdin);
printf("\n Input choice 'b' to break:");
choice = getchar();
}
fflush(stdin);
while(1)
{
printf("\n Input choice 'b' to break:");
printf("\n Input the key value want to deletedir:");
scanf("%c", &Info);
if (Info == 'b')
break;
Tree = Delete_Element(Tree, Info, &H);
printf("\n Tree is:\n");
Output(Tree, 1);
}
}

HEAP SORT
A heap is an ordered balanced binary tree in which the value of the node at the root of any sub-
tree is less than or equal to the value of either of its children. This inherent ordering implies that
only valued items may be placed in the heap. In general a heap represents a table of n elements or
records satisfying the following property:
n and i = j Ni for 2 Nj | j/2 |
A heap satisfying above definition is called a mim-heap.
Algorithm of Heap construction
Heap sort algorithm
/*PROGRAM IMPLEMENTING HEAP SORT ALGORITHM */
# include<stdio.h>
void heap_sort(int *, int );
void create_heap(int *, int);
void display(int *, int);
/* Definition of the function */
void create_heap(int list[], int n )
{
int k, j, i, temp;
for(k = 2 ; k <= n; ++k)
{
i = k ;
temp = list[k];
j = i / 2 ;
while((i > 1) && (temp > list[j]))
{
list[i] = list[j];
i = j ;
j = i / 2 ;
if ( j < 1 )
j = 1 ;
}
list[i] = temp ;
}
}
/* End of heap creation function */
/* Definition of the function */
void heap_sort(int list[], int n)
{
int k, temp, value, j, i, p;
int step = 1;
for(k = n ; k >= 2; --k)
{
temp = list[1] ;
list[1] = list[k];
list[k] = temp ;
i = 1 ;
value = list[1];
j = 2 ;
if((j+1) < k)
if(list[j+1] > list[j])
j ++;
while((j <= ( k-1)) && (list[j] > value))
{
list[i] = list[j];
i = j ;
j = 2*i ;
if((j+1) < k)
if(list[j+1] > list[j])
j++;
else
if( j > n)
j = n ;
list[i] = value;
} /* end of while statement */
printf("\n Step = %d ", step);
step++;
for(p = 1; p <= n; p++)
printf(" %d", list[p]);
} /* end for loop */
}
/* Display function */
void display(int list[], int n)
{
int i;
for(i = 1 ; i <= n; ++ i)
{
printf(" %d", list[i]);
}
}
/* Function main */
void main()
{
int list[100];
int i, size = 13 ;
printf("\n Size of the list: %d", size);
for(i = 1 ; i <= size ; ++i)
{
list[i] = rand() % 100;
}
printf("\n Entered list is as follows:\n");
display(list, size);
create_heap(list, size);
printf("\n Heap\n");
display(list, size);
printf("\n\n");
heap_sort(list,size);
printf("\n\n Sorted list is as follows :\n\n");
display(list,size);
}
GRAPHS
BASIC CONCEPTS AND DEFINITIONS
A Graph G is defined as a set of two tuples that is G=(V, E), where V represents set of vertices of G
and E represents the set of edges of G.
E1
E2 E3
E7 E8 E9
E4
E4 E5
GRAPH G
The figure above represents a Graph. Now here in Graph G =(V, E), an edge that is directed from
one vertex to another is called directed edge, while an edge which has no specific direction is called
an undirected edge. A graph in which every edge is directed is called a directed graph or a digraph.
A graph in which every edge is undirected is called undirected graph. If some edges in a graph are
directed and some edges are undirected then the graph is called mixed graph.
E be a"Let G = (V, E) be a graph and e directed edge associated with ordered pair of vertices (v1,
v2). Then the edge e is said to be initiating from the vertex v1 and terminating at the vertex v2.
Thus vertex v1 and v2 are also called the initial and terminal vertices of edge E, which joins the
vertices v1 and v2 in graph G. It is an incident to the"e, e vertices v1 and v2. An edge of a graph
that joins a vertex to it is called sling. The direction of the loop is of no significance; hence it can be
considered either a directed or undirected edge.
When in a graph, two or more than two edges are used to join two vertices, such edges are called
parallel edges and the graph is called parallel edges and the graph is called multi-graph.
There are three parallel edges between the vertices 1 and 4 and three parallel edges between
vertices 5 and 6. If there is only one edge between a pair of vertices in a graph then such a graph
is called simple graph. Fig 4.1 represents a simple graph. A graph with edge value is called
weighted graph.
Fig 4.3 5
6 3 4 1
2
WEIGHTED GRAPH
In a graph a vertex, which is not adjacent to any other vertices in the graph, is called an isolated
vertex. A graph containing only isolated vertices is called null graph or in other words a graph
without an edge is called a null graph.
In a directed graph for any vertex v the number of edges which have vertex v as their initial vertex
is called the out-degree of v. The number of edges, which have v as their terminal vertex, is called
the in-degree of v. The sum of out-degree and in-degree of a vertex is called the total degree of
the vertex. In case of undirected graph, the degree of a vertex is the number of edges incident on
it. The total degree of a loop is 2 and degree of an isolated vertex is 0.
A sequence of edges of a digraph such that the terminal vertex of an edge sequence in the initial
vertex of the next edge if exists is called the path.
REPRESENTATION OF GRAPH
There are two popular ways that are used to maintain a graph in a computer memory. These are :
1 Sequential
2 Linked list
SEQUENTIAL REPRESENTATION
The graphs can be represented as matrices in sequential representation. There are two most
common matrices. These are:
1 Adjacency
2 Incidence
The adjacency matrix is a sequence matrix with one row and one column for each vertex. The
values of the matrix are either 0 or 1. A value of 1 for row i and column j implies that edge eij
exists between vi and vj vertices. A value of 0 implies that there is no edge between vertex vi and
vj . In other words we can say that if graph G consists of v1,v2,v3,..vn vertices then the
adjacency matrix A = [aij] of the graph G is the n x n matrix and can be defined as :
1 If vi is adjacent to vj (that is if there is an edge between vi and vj)
aij = 0 If there is no edge between vi and vj
Such a matrix A, which contains entries of only 0 and 1, is called a bit matrix or a Boolean matrix.
The adjacency matrix A of the graph G does depend on the ordering of the nudes of G; that is, a
different ordering of nodes may result in different adjacency matrix. However the matrices
resulting from two different orderings are closely related in that one can be obtained from the other
by simply interchanging rows and columns. Suppose G is an undirected graph. Then the adjacency
matrix A of G will be a symmetric matrix, i.e., one in which aij = aji for every i and j. This follows
from the fact that each undirected edge [u, v] corresponds to the two directed edges (u, v) and (v,
u). The above matrix representation of a graph may be extended to multigraphs. Specifically, if G
is a multigraph, then the adjacency matrix of G is the m x m matrix A = (aij) defined by setting aij
equal to the number of edges from vi to vj.
v1 v2
v3 v4
Adjacency matrix for above graph
0 1 1 0
1 0 1 1
1 1 0 1
0 1 1 0
The incidence matrix consists of a row for every vertex and a column for every edge. The values of
the matrix are -1, 0 or 1. If the kth edge is (vi , vj), the kth column has a value 1 in the ith row, -1
in the jth row and 0 elsewhere.
PATH MATRIX
Let G be a simple directed graph with m nodes, v1, v2, v3, . . . . , vm. The path matrix or
reachability matrix of G is the m-square matrix P = (pij) defined as follows :
1 if there is a path from vi and vj
Pij = 0 otherwise
Suppose there is a path from vi to vj. vj , or there must be a-Then there must be a simple path
from vi to vj when vi cycle from vi to vj when vi = vj. Since G has only m nodes, such a simple
path must have length m - 1 or less, or such a cycle must have length m or less.
SHORTEST PATH ALGORITHM
DIJKSTRAS TECHNIQUES
This technique is used to determine the shortest path between two arbitrary vertices in a graph.
Let, weight w(vi, vj) is associated with every edge(vi, vj) in a given graph G. Furthermore, the
weights are such that the total weight from vertex vi to the vertex vk via vertex vj is w(vi, vj) +
w(vj, vk). Using this technique, the weight from a vertex vs (starting of a path) to the vertex vt
(the end of the path) in a graph G for a given path (vs, v1) , (v1, v2) , (v2, v3) ,. . . , (vi, vt) is
given by w(vs, v1) + w(v1, v2) + w(v2, v3) + . . . . w(vi, vt) . In a graph there are many possible
paths between vs and vt .
Dijkatras technique is based on assigning labels to each vertex. The label is equal to the distance
(weight) from the starting vertex to that vertex. Obviously, the starting vertex vs has a label 0. A
label can be in one of two states - temporary or permanent. A permanent label that lies along the
shortest path while a temporary label is one that has uncertainty as to whether the label is the
shortest path.
Dijkstras technique gradually changes the temporary labels to permanent labels until the end
vertex has a permanent label. At each step, the aim is to make the temporary labels shorter by
finding paths to the associated vertices using the shortest paths to the permanent labeled vertices.
After this the temporary label with the smallest value is made permanent. This process eliminates
one temporary vertex at each step, ensuring that the shortest path from vs to vt will eventually be
found.
Dijkstras Algorithm
to all vertices_Step 1: Assign a temporary label l(vi) = except vs.
Step 2: [Mark vs as permanent by assigning 0 label to it ]
l(vi) = 0
Step 3: [ Assign value of vs to vr where vr is last vertex to be made permanent ]
vr = vs
Step 4: if l(vi) > l(vk) + w(vk, vi)
l(vi) = l(vk) + w(vk, vi)
Step 5: vr = vi
Step 6: If vt has tempory label, repeat step 4 to step 5 otherwise the value of vt is permanent
label and is equal to the shortest path vs to vt.
Step 7: Exit
Example : Find the shortest path between vertex vs to vt .
vs 4 vt
5 1
2
7
v2 v3
3
Weight matrix of above graph is :
vs v2 v3 vt
vs 0 5 0 4
W = v2 7 0 0 2
v3 0 3 0 0
vt 0 0 1 0
If we replace the elements, which have 0 with 9999(very large value) except diagonal elements,
we get a distance matrix D.
vs v2 v3 vt
vs 0 5 9999 4
D = v2 7 0 9999 2
v3 9999 3 0 9999
vt 9999 9999 1 0
Now we have to travel from vs to vt in the above graph. There are two possible route
(a) from vs to vt (direct),
(b) from vertex vs to v2 and then from v2 to vt.
The distance from to possible routes are 4 and 7 represented.
Step 1, Step 2 and Step 3: Assign labels as follows and set vr = vs = v1.
vs v2 v3 vt
label: 0 9999 9999 9999
permanent: Y N N N
Step 4 and Step 5: Redefine temporary labels as follows:
Label(v2) = min(9999, 0 + 5 ) = 5
Label(v3) = min(9999,0+9999)=9999
Label(vt) = min(9999,0 + 4) = 4
Make Label(v2) permanent, vr=v2
vs v2 v3 vt
Label: 0 5 9999 9999
Permanent: Y Y N N
Step 6: Repeat Step 4 and Step 5, redefine the temporary labels as follows:
Label (v3) = min(9999,7 + 0)=7
Label (vt) = min(4,7+2) =4
Make Label(v3) permanent, vr = v3
Vs v2 v3 vt
Label: 0 5 7 9999
Permanent: Y Y Y N
Again repeat Step 4 and Step 5, redefine
Label (vt) = min(4,0+9999)
Make Label(vt)permanent set vr = vt
vs v2 v3 vt
Label: 0 5 7 4
Permanent: Y Y Y Y
Label (vt) is permanent. The shortest path length is 4.
The program to implement Dijkstras Algorithm.
/* DIJKSTRA METHOD */
# include<stdio.h>
#define size 20
#define p 1
#define t 0
#define infinity 9999
struct label
{
int predecessor;
int length;
int flag;
};
int k,min,count;
struct label state[size];
int visit_path[size];
int Short_path(int a[size][size], int , int , int ,int path[size], int *);
void Input(int , int a[size][size]);
void Output(int , int a[size][size]);
/* Shortest path computing function */
int Short_path(int a[size][size], int n, int s, int t, int path[size] , int *dist)
{
int i;
int t1,t2;
*dist = 0;
for(i=0;i<=n;i++)
{
state[i].predecessor = 0;
state[i].length = infinity;
state[i].flag = T;
}
/* Make source vertex permanent */
state[s].predecessor = 0;
state[s].length = 0;
state[s].flag = P;
/* Start from source vertex */
k = s;
do
{
// Check all the paths from kth vertex and find their distance from k vertex
for(i=0; i<= n; i++)
{
if(( a[k][i]> 0) && (state[i].flag ==T))
{
if((state[k].length + a[k][i]) < (state[i].length))
{
state[i].predecessor = k;
state[i].length = state[k].length + a[k][i];
}
}
}
min = infinity;
k = i;
for(i = 0; i <= n ; i++)
{
if((state[i].flag ==T) && (state[i].length < min))
{
min = state[i].length;
k = i;
}
}
if( k == 0)
return (0);
state[k].flag = p;
}while(k != t);
/* Store optimal path */
k = t;
count = 1;
do
{
visit_path[count] = k;
count ++;
k = state[k].predecessor;
}while(k != 0);
// Reverse the vertices since algorithm stores path in reverse direction
count --;
for( i = 0 ; i <= count ; i ++)
{
path[i] = visit_path[count - i + 1 ];
for( i = 1 ; i < count ; i ++)
{
t1 = path[i];
t2 = path[i + 1];
*dist += a[t1][t2];
}
return (count);
}
/* Input function */
void Input(int n, int a[size][size])
{
int i,j;
printf(\n Input adjacency matrix \n);
for( i = 0; i< n ; i ++)
{
for(j = 0; j< n ; j ++ )
{
scanf(%d,&a[i][j]);
}
printf(\n);
}
}
/* Output function */
void Output(int n , int a[size][size])
{
int i,j;
printf(\n Adjacency matrix \n);
for( i = 0; i< n ; i ++)
{
for(j = 0; j< n ; j ++ )
{
printf( %d,a[i][j]);
}
printf(\n);
}
}
/* Function main */
void main()
{
int a[size][size];
int path[size];
int org, dest, dist;
int count, i, n;
printf(\n Input the number of vertices in the graph : );
scanf(%d, &n);
Input(n,a);
Output(n, a);
printf(\n Input starting vertex : );
scanf(%d,&org);
printf(\n Input destination : );
scanf(%d,&dest);
count = Short_path(a, n, org , dest , path, &dist);
if(dist)
{
printf(\n Shortest path : %d,path[i]);
for(i =2; i<= count; i ++)
printf ( => %d,path[i]);
printf(\n Minimum distance = %i, dist);
}
else
printf( \n Path does not exise \n);
}
ADJACENCY LIST
Let G = (V, E) is a graph with n vertices. This graph can be represented by n x n adjacency matrix.
The n linked lists represent the n rows of the adjacency matrix A and there is one linked list for
each vertex in G. The vertices in the list L represent the vertices that are adjacent to the vertex L,
each vertex represented by two fields: Vertex and Link. The Vertex fields contain the indices of the
vertices adjacent to the vertex L. The adjacency matrix for G is as follows :
v1 v2 v3 v4 v5 v6
v1 0 1 0 0 1 0
v2 0 0 1 1 1 0
v3 0 0 0 0 1 0
A = v4 1 0 1 0 0 1
v5 0 0 0 0 0 0
v6 0 1 0 0 1 0
Directed Graph
Adjacency lists for the graph G
The number of distinct vj in the graph with n vertices is n(n - 1)/2.-unordered pairs(vi, vj) with vi
This is the maximum number of edges in any n vertex undirected graph. An n vertex undirected
graph with exactly n(n - 1)/2 edges is said to be complete. In the case of a directed graph having n
vertices the maximum number of edges is n(n -1).
OPERATIONS ON GRAPHS
Suppose a graph G is maintained in memory by linked representation.
GRAPH(NODE, NEXT, ADJ, START, AVAILN, DEST, LINK, AVAILE)
Searching in a Graph
Suppose we want to find the location LOC of a node N in a Graph G. The procedure for this is:
Inserting in a Graph Suppose a node is to be inserted in the graph.
Deleting a node from the graph Suppose a node is to be deleted from the graph.
GRAPH TRAVERSAL
Some times it is required to examine all the vertices in a graph in some systematic orders, as we
have seen in the case of binary trees where we use pre order ,postorder or inorder to examine the
vertices . For examining all the vertices we start from the root for trees while in the graph we start
examination from an arbitrary vertex. There are two popular techniques for examination of the
graphs. These are:
1 Depth first search(DFS)
2 Breadth first search(BFS)
DEPTH FIRST SEARCH (DFS)
This is similar to preorder examination of an order tree. Suppose the examination has just
examined a vertex vi and let w1, w2, w3,..wk, be the vertices adjacent to vi. We next examine wi
and keep w2,w3,..wk waiting. After examining w1 we examine all the vertices to which it is
adjacent to before returning to examine w2, w3, ..wk.
A 1
3
B 2 C D E 5 6 F 4
Consider the graph illustrated above. The DFS strategy results the examination indicated by the
arrows, assuming that each edge has been assigned a value of 1. Starting at vertex A the
examination numbers all the vertices down until vertex F is reached , where all the adjacent
vertices have already been marked(examined). The DFS algorithm returns to C, which still has an
unlabeled adjacent vertex D. After vertex D and E are labeled, all vertices are numbered and the
examination is complete.
A graph is called bi-connected if there is no single vertex whose removal causes the graph break
into two or more pieces. A vertex whose removal causes the graph to become disconnected is
called a cut-vertex.
A vital communication network may bedescribed by a graph, allowing each vertex to representing a
communication line and each edge indicating the presence of an interconnection between the lines.
For a cut-vertex destruction of the line would result in a break down of communications. If the
graph is bi-connected the removal of one line(vertex) would not affect the communication, since
there will still be other links.
The DFS algorithm is illustrated below:
The result of the program segment tested on the graph G is illustrated in fig below.
The adjacency matrix A of the graph is as follows:
0 1 1 0 0 0 0 0
0 0 0 1 1 0 0 0
0 0 0 0 1 0 0 0
A = 0 0 0 0 0 0 0 1
0 0 0 0 0 1 0 1
0 0 0 0 0 0 1 0
0 0 1 0 0 0 0 0
0 0 0 0 0 1 1 0
Program to illustrate Depth First Search Algorithm
/* DEPTH FIRST SEARCH TECHNIQUE */
/* DFS.C */
# include<stdio.h>
# define size 20
# define T 1
# define F 0
struct Edge
{
int terminal;
struct Edge *next;
};
struct Vertex
{
int visit;
int vertex_no;
char info;
int path_length;
struct Edge *Edge_Ptr;
};
void Table(int , int matrix [size][size], struct Vertex vert[size]);
struct Edge *Insert_Vertex (int , struct Edge *);
void DFS ( int , int *dist, struct Vertex vert [size]);
void Input(int, int a [size][size]);
void Output(int, int a [size][size]);
struct Edge * Insert_Vertex (int vertex_no, struct Edge *first)
{
struct Edge *new1, *current;
new1 = (struct Edge *) malloc(sizeof(struct Edge));
new1->terminal = vertex_no;
new1->next = NULL;
if (!first)
return (new1);
for (current = first; current->next; current = current->next);
current->next = new1;
return (first);
}
/* Initializing entries */
void Table(int vertex_num, int matrix [size][size],
struct Vertex vert[size])
{
int i, j;
for (i = 0; i < vertex_num; i++)
{
vert [i].visit = F;
vert [i].vertex_no = i+1;
vert [i].info = 'A'+ i;
vert [i].path_length = 0;
vert [i].Edge_Ptr = NULL;
}
for (i =0; i < vertex_num ; i++)
for (j =0; j < vertex_num ; j++)
if (matrix [i][j] > 0)
vert [i].Edge_Ptr = Insert_Vertex (j, vert [i].Edge_Ptr);
}
/* Computing path length */
void DFS ( int index, int *dist,
struct Vertex vert [size])
{
struct Edge *Link;
vert [index].visit = T;
vert [index].path_length = *dist;
*dist += 1;
for ( Link = vert [index].Edge_Ptr; Link; Link = Link->next)
if (vert [Link->terminal].visit == F)
DFS (Link->terminal, dist, vert);
}
/* Input function to read adjacency matrix */
void Input(int number, int a [size][size])
{
int i, j;
printf("\n Input the adjacency matrix \n");
for (i =0; i < number; i++)
{
for (j=0; j < number; j ++)
{
scanf("%d", &a [i][j]);
}
printf("\n");
}
}
/* Output function */
void Output(int number, int a [size][size])
{
int i, j;
printf("\n Adjacency matrix \n");
for (i = 0; i < number; i++)
{
for (j = 0; j < number; j ++)
{
printf(" %d", a [i][j]);
}
printf("\n");
}
}
/* Function main */
void main()
{
int i;
int number, index, dist;
int a [size][size];
struct Vertex vert [size];
struct Edge *List;
printf("\n Input the number of vertices in the graph: ");
scanf("%d", &number);
Input(number, a);
Output(number, a);
Table(number, a, vert);
printf("\n Input the starting vertex 0- %d:", number-1);
scanf("%d", &index);
dist = 0;
DFS (index, &dist, vert);
printf("\n Path length of the vertex from %c", vert[index].info);
printf("\n Vertex Length Vertex Connectivity \n ");
for (i = 0; i < number; i++)
{
printf("\n %c %d ", vert[i].info, vert[i].path_length);
for (List= vert[i].Edge_Ptr; List; List = List->next)
{
printf(" ");
putchar(List->terminal+'A');
}
}
}
BREADTH FIRST SEARCH (BFS)
Breadth first search(examination) of a graph is similar to level by level examination of an ordered
tree. If the examination has just visited a vertex v, then it visits all the vertices adjacent to v by
putting the vertices adjacent to those in a waiting queue to be examined, after all vertices adjacent
to v have been visited. Consider the undirected graph G illustrated below. A breadth first
examination beginning at vertex A of the graph G would first visit A and then B and C. Next D,E,F
and G will be visited and finally H. The program segment to illustrate the BFS algorithm
/* BREADTH FIRST SEARCH TECHNIQUE */
/* BFS.C */
# include<stdio.h>
# define size 20
# define T 1
# define F 0
struct Edge
{
int terminal;
struct Edge *next;
};
struct Vertex
{
int visit;
int vertex_no;
char info;
int path_length;
struct Edge *Edge_Ptr;
};
struct Q
{
int info;
struct Q *next;
};
void Table(int , int matrix [size][size], struct Vertex vert[size]);
struct Edge *Insert_Vertex (int , struct Edge *);
void BFS ( int , struct Vertex vert [size]);
void Input(int, int mat [size][size]);
void Output(int number, int mat [size][size]);
struct Q *Insert_Queue(int vertex_no, struct Q *first);
struct Q *Delete_Queue(int *vertex_no, struct Q *first);
/* Insert vertex into connectivity list */
struct Edge * Insert_Vertex (int vertex_no, struct Edge*first) {
struct Edge *new1, *current;
new1 = (struct Edge *) malloc(sizeof(struct Edge));
new1->terminal = vertex_no;
new1->next = NULL;
if (!first)
return (new1);
for (current = first; current->next; current = current->next);
current->next = new1;
return (first);
}
/* Insert vertices into queue */
struct Q * Insert_Queue(int vertex_no, struct Q *first)
{
struct Q *new1, *current;
new1 =(struct Q *) malloc(sizeof(struct Q));
new1->info = vertex_no;
new1->next = NULL;
if (!first)
return (new1);
for (current = first; current->next; current = current->next);
current->next = new1;
return (first);
}
struct Q * Delete_Queue(int *vertex_no, struct Q *first)
{
struct Q *previous;
if (!first)
return (NULL);
*vertex_no = first->info;
previous = first;
first = first->next;
free(previous);
return (first);
}
/* Initializing entries */
void Table(int vertex_num, int matrix [size][size],
struct Vertex vert[size])
{
int i, j;
for (i = 0; i < vertex_num; i++)
{
vert [i].visit = F;
vert [i].vertex_no = i+1;
vert [i].info = 'A'+ i;
vert [i].path_length = 0;
vert [i].Edge_Ptr = NULL;
}
for (i =0; i < vertex_num ; i++)
for (j =0; j < vertex_num ; j++)
if (matrix [i][j] > 0 )
vert [i].Edge_Ptr = Insert_Vertex (j, vert [i].Edge_Ptr);
}
/* Computing path length */
void BFS ( int index, struct Vertex vert [size])
{
struct Q *queue = NULL;
struct Edge *Link;
vert [index].visit = T;
queue = Insert_Queue(index, queue);
while(queue)
{
queue = Delete_Queue(&index, queue);
for ( Link = vert [index].Edge_Ptr; Link; Link = Link->next)
{
if (vert [Link->terminal].visit == F)
{
vert[Link->terminal].visit = T;
vert[Link->terminal].path_length=vert[index].path_length+1;
queue = Insert_Queue(Link->terminal, queue);
}
}
}
}
/* Input function to read adjacency matrix */
void Input(int number, int mat [size][size])
{
int i, j;
printf("\n Input the adjacency matrix \n");
for (i =0; i < number; i++)
{
for (j=0; j < number; j ++)
{
scanf("%d", &mat [i][j]);
}
printf("\n");
}
}
/* Output function to display adjacency matrix */
void Output(int number, int mat [size][size])
{
int i, j;
printf("\n Adjacency matrix \n");
for (i =0; i < number; i++)
{
for (j=0; j < number; j ++)
{
printf(" %d", mat [i][j]);
}
printf("\n");
}
}
/* Function main */
void main()
{
int i, number, index;
int mat [size][size];
struct Vertex vert [size];
struct Edge *List;
printf("\n Input the number of vertices in the graph: ");
scanf("%d", &number);
Input(number, mat);
Output(number, mat);
Table(number, mat, vert);
printf("\n Input the starting vertex 0- %d :",number-1);
scanf("%d", &index);
BFS (index, vert);
printf("\n Path length of the vertex from %c", vert[index].info);
printf("\n Vertex Length Vertex Connectivity \n ");
for (i = 0; i < number; i++)
{
printf("\n %c %d ",vert[i].info, vert[i].path_length);
for (List= vert[i].Edge_Ptr; List; List = List->next)
{
printf(" ");
putchar(List->terminal+'A');
}
}
}
HASHING
The search time of each algorithm discussed so far depends on the number n of elements in the
collection S of data. This section discusses a searching technique, called hashing or hash
addressing, which is essentially independent of the number n. The terminology whish we use in our
presentation of hashing will be oriented toward file management. First of all, we assume that there
is a file F of n records with a set K of keys, which uniquely determine the records in F. Secondly,
we assume that F is maintained in memory by a table T of m memory locations and that L is the
set of memory addresses of the locations in T. For notational convenience, we assume that the
keys in K and the addresses in L are (decimal) integers. ( Analogous method will work with binary
integers or with keys which are character strings, such as names, since there are standards ways
of representing strings by integers.)
Example : Suppose a company with 68 employs assigns a 4-digit employee number to each
employee which is used as the primary key in the companys employee file. We can, infect, use the
employee number as the address of the record in memory. The search will require no comparisons
at all. Unfortunately, this technique will require space for 10,000 memory locations, whereas space
for fewer than 30 such locations would actually be used. Clearly, this tradeoff space for time is not
worth the expense.
The general idea of using the key to determine the address of a record is an excellent idea, but it
must be modified so that a great deal of space is not wasted. This modification takes the form of a
function H from the set K of keys into the set L of memory addresses. Such a function,
H : K L
Is called a Hash function or Hashing function. Unfortunately, such a function H may not yield
distinct values : it is possible that two different keys k1 and k2 will yield the same Hash address.
This situation is called Collision, and some method must be used to resolve it. Accordingly, the
topic of Hashing is divided into two parts :
(1) Hash Functions
(2) Collision Resolution
We discuss these two parts separately.
HASH FUNCTIONS
The two principal L are as follows. First ofcriteria used in selecting the Hash function H : K all,
the function H should be very easy and quick to compute. Second the function H should , as far as
possible, uniformly distribute the Hash addresses through the set L so that there are a minimum
numbers of collisions. Naturally, there is no guarantee that the second condition can be completely
fulfilled without actually knowing beforehand the keys and addresses. However , certain general
techniques do help. One technique is to chop a key k into pieces and combine the pieces in some
way to form the Hash address H (k). ( The term Hashing comes from this technique of
Chopping a key into pieces.)
We next illustrate some popular hash functions. We emphasize that the computer can easily and
quickly evaluate each of these Hash functions.
(a) Division Method : Choose a number m larger than the number n of keys in K. ( The number
m is usually chosen to be a prime number or a number without small divisors, since this frequently
minimizes the number of collisions.) The hash function H is defined by
H(k) = k( mod m) or H(k) = k(mod m) + 1
Here k(mod m) denotes the remainder when is divided by m.
The second formula is used when we want the Hash addresses to range from 1 to m rather than
from 0 to m - 1.
(b) Midsquare Method : The key k is squared. Then the hash function H is defined by
H(k) = l
Where l is obtained by deleting digits from both ends of k2. we emphasize that the same positions
of k2 must be used for all of the keys.
(c) Folding Method : The key k is partitioned into a number of parts , k1,,kr , where each
part, except possibly the last, has the same number of digits as the required address. Then the
parts are added together , ignoring the last carry. That is ,
H(k) = k1 +k2 + k3+.+kr
Where the leading - digit carries , if any, are ignored. Sometimes , for extra milling , the even -
numbered parts, k2, k4, ., are each reversed before the addition.
COLLISION RESOLUTION
Suppose we want to add a new record R with key k to our file F, but suppose the memory location
address H(k) is already occupied. This situation is called collision. This sub section discusses two
generah ways of resolving collisions. The particular procedure that one chooses depends on many
factors. One important factor is the ratio of the number n of keys in K (which is a number of
records in F) to the number m of Hash addresses in L .
= n /m, is called the load factor.-This ratio,
First we show that collisions are almost impossible to avoid. Specifically, suppose a student class
has 24 students and suppose the table has space for 365 records. One random Hash function is to
choose the students birthday as the Hash address. Although the 7% is very small, it can be shown
that there is a- = 24/365 -load factor better then fifty - fifty chance that two of the students
have the same date of birth.
The efficiency of a Hash function with a Collision Resoluton procedure is measured by the average
number of probes (key comparisons) needed to find the location of the record with a given key k.
The efficiency depends. specifically, we are interested in the following-mainly on the load factor
two quantities :
) = avg. number of probes for a successful-S( search
) = avg. number of probes for an unsuccessful search-U(
Open addressing : Linear Probing and Modifications
Suppose that a new record R with key k is to be added to the memory table T, but that the
memory location hash address H (k) = h is already fulfilled. One natural way to resolve the collision
is to assign R to the first available location following T [h]. (We assume that the table T with m
locations is circular, so that T[1] comes after T[m]. ) Accordingly with such a collision procedure ,
we will search for the record R in the table T by linearly searching the location T[h],T[h + 1],T[h +
2],..until finding R or meeting an empty location, which indicates an unsuccessful search.
The above Collision Resolution is called linear Probing. The average numbers of probes for a
successful search and for an unsuccessful search are known to be the following respective
quantities :
)2)-) = 1/2( 1+1/(1--) ) and U(-) = 1/2( 1 + 1/(1--S(
-( Here = n/m is the load factor.)
One main disadvantage of Linear probing is that records tend to cluster, that is, appear next to one
another, when the load factor is greater then 50%. Such a clustering substantially increases the
average search time for a record. Two techniques of minimize clustering are as follows :
(1) Quadratic Probing : Suppose a record R with key k has the Hash address H(k) = h. Then,
instead of searching the locations with addresses h , h + 1, h + 2,.,we linearly search the location
with addresses.
h, h +1, h+4, h+9, h+16,,h+i2 , .
If the number m of locations in the table T is a prime number , then the above sequence will access
half of the location in T .
(2) Double Hashing : Here a second hash function H is used for resolving a collision, as follows.
Suppose a record R with key k has the hash m. Then we linearly search the locations
with-addresses H(k) = h and H(k) = h addresses H, h+h, h+2h, h+3h, .
If m is a prime number, then the above sequence will access all the locations in the table T.
Remark: One major disadvantage in any type of open addressing procedure is in the
implementation of deletion. Specifically, suppose a record R is deleted from the location T[r].
Afterwards, suppose we meet T[r] while searching for another record R. This dose not necessarily
means that the search is unsuccessful. Thus, when deleting the record R, we must label the
location T[r] to indicate that it previously did contain a record. Accordingly, open addressing may
seldom be used when a file F is constantly changing.
Chaining
Chaining involves maintaining two tables in memory. First of all, as before, there is a table T in
memory which contains the records in F, except that T now has an additional field LINK which is
used so that all records in T with the same hash address h may be linked together to form a linked
list. Second, there is a hash address table LIST that contains pointers to the linked lists in T.
Suppose a new record R with key k is added to file F. We place R in the first available location in
the table T and then add R to the linked list with pointer LIST [H (k)]. If the linked lists of records
are not sorted, than R is simply inserted at the beginning of its linked list. Searching for a record or
deleting a record is nothing more than searching for node or deleting a node from a linked list.
The average number of probes, using chaining, for a successful search and for an unsuccessful
search are known to be the following approximate values:
- + - e--) - and U (- 1 + -) -S (
Here the = n/m may be greater than 1, since the number m of hash addresses-load factor in L
(not the number of location in T) maybe less then the number n of records in F.

SEARCHING AND SORTING
In this chapter we will discuss some sorting and searching techniques. First we will take searching
techniques.
LINEAR SEARCH
This is the simplest technique to find out an element in an unsorted list. Let we have an unsorted
list I, which consists of n elements and want to search the value of a particular element in the list,
as, illustrated in Fig (5.1).
In this technique the value of the key is compared with the first element of the list, if match is
found then the search is terminated. Otherwise next element from the list is fetched and compared
with the key and this process is continued till the key is found or list is completely exhausted. For
example, Fig (4.2) represents the list of elements in the memory, having 6 elements
22,33,66,05,44,89 and we want to search for key == 05. Fig (4.2), Fig (4.2a), Fig (4.2b), Fig
(4.2c) illustrates the idea.
Fig (4.3) Algorithm for Linear Search
The algorithm for linear search is given in Fig (4.3). Following program segment implements the
above discussion (lsearch.c).
/* LINEAR SEARCH */
/* 1search. c */
#include<stdio.h>
int search ;
int flag ;
int input ( int *, int , int );
void linear_search (int *,int , int );
void display ( int *,int );
/* Definition of function */
void linear-search (int 1[] , int n , int element )
{
int k ;
flag = 1 ;
for ( k=0 ; k< n ; k++ )
{
if (1 [k] = element )
{
printf ( \n Search is successful \n );
printf ( \n Element : % i Found at Location : % i , element , k+1 );
flag = 0 ;
}
}
if ( flag )
printf ( \n Search is unsuccessful ) ;
}
void display ( int list [] , int n )
{
int i ;
for ( i = 0 ; i < n ; i++ )
{
printf ( %d , list [i] ) ;
}
}
input (int list [] , int number , int key )
{
int i ;
number = 20 ;
key = 30 ;
printf ( Number of elements in the list : %d , number ) ;
for ( i = 0 ; i < 20 ; i+ + )
{
list [i] = rand ( ) % 100 ;
}
printf ( \n Element to be searched : % d , key ) ;
search = key ;
return number ;
}
void main ( )
{
int number , key , list [ 200] ;
number = input ( list , number , key ) ;
key = search ;
printf ( \n Entered list as follows : \n ) ;
display ( list , number ) ;
linear-search ( list ,number , key ) ;
printf (\n in the following list \n ) ;
display ( list , number ) ;
}
BINARY SEARCH
Binary search works for sorted lists and is a very efficient searching technique. It is used to find the
location of a given element or record in a list. Other information associated with the element can
also be fetched if required. To find the location of a file in the computer directory one can use this
searching technique. If we are on the Internet then it is not a easy task using liner search to find
out the information about some records or files. For this one prefers Binary searching techniques.
Let low represents lower limit of the list 1 , high upper and mid is average of low and high that is
middle of the lower and upper limits , it is
mid =( low + high )/2

index 0 1 2 3 4 5 6 7 8 9 10 11 12
99 11 22 40 55 60 88 80 77 66 44 33 30
Fig (4.4) List in the memory
Figure 4.5
We compared the middle element with key to be searched. If the value of middle element is
greater than key , then key will exist in lower half of the list, take high = mid 1 and find new
value of mid , i.e.,
mid =( low +high )/2
Otherwise, key will exist in upper half and take
Low =mid + 1
And mid = (low + high)/2
Fig (4.6) Algorithm for Binary Search
The following program segment implements the Binary Search Algorithm.
/* Binary.c */
#include <stdio.h>
int binary_search(int array[], int value , int size)
{
int found = 0;
int high = size 1, low = 0, mid;
mid = (high + low )/2;
printf( \n\n Looking for %d\ , value);
while(( !found) && (high >= low))
{
printf(Low %d Mid %d High %d \n ,low,mid,high);
if( value == array[mid])
found = 1;
elseif( value < array[mid])
high mid 1;
else
low = mid + 1;
mid = (high + low)/2;
}
return(( found) ? mid: -1);
}
void main(void)
{
int array[100],i;
for( i = 0; i < 100 ; i++)
array[i] = i + 20;
printf(Result of search %d\n, binary_search(array,33,100));
printf(Result of search %d\n, binary_search(array,75,100));
printf(Result of search %d\n, binary_search(array,1,100));
}
BUBBLE SORT
It is very simple sorting technique. However, this sorting technique is not efficient in comparison to
other sorting techniques. But for smaller lists this sorting technique works fine. Suppose we sort
the elements in descending order, the bubble sort loops through the elements in the list comparing
the adjacent element and moves the largest element to the top of the list.
The bubble sort algorithm is given in Fig (4.8). From this algorithm it is clear that bubble sort
places the smallest element in the proper position and selects the second element and searches for
the second smallest element .Fig (4.7), Fig (4.7a), Fig (4.7b), Fig (4.7c) illustrate the complete
operation performed on 5-element list.


From the algorithm shown in Fig ( 4.8 ) it is clear that for the pass i the inner loop performs the n-i
comparisons ( because only n-i elements are examined ) to find the smallest element. Total
number of comparisons for all the passes is :
n - 1
n - i-E(n) =
i = 0
(n 1) + (n 2) + (n 3) + ***+ 2 + 1
n( n 1) / 2
n2 / 2 + O ( n ) i.e. O ( n2 )
Following program segment illustrates the algorithm given in Fig ( 4.8 )
/* bubble.c */
# include <stdio .h>
# include < stdio .h>
void bubble_sort ( int array [] , int size )
{
int temp, i, j;
for ( i= 0; i < size; i + + )
for ( j = 0; j < size i l; j + + )
if ( array [j] < array [j + l])
{
temp = array [j];
array [j] = array [j + l];
array [j + l] = temp;
}
}
void main ( void )
{
int values [30], i ;
printf (\n Unsorted list is as follows \n )
for (i =0 ; i < 10 ; i + + )
{
values [i] =rand ( ) % 100 ;
printf ( %d, values [i] ) ;
}
bubble_sort ( values, 10 ) ;
printf (\n Sorted list is as follows \n ) ;
for ( i = 0 ; i < 10 ; i + + )
printf ( % d, values [i] ) ;
}
INSERTION SORT
Suppose l is the list of n elements. The insertion sort technique scans the list l[l] to l[n], inserting
each element into its proper position in the previously sorted sub-list l[l], l[2]***l[i-l].
Step =1 -0 7 3 4 1 8 2 6 5
Step = 2 -0 3 7 4 1 8 2 6 5
Step = 3 -0 3 4 7 1 8 2 6 5
Step = 4 -0 1 3 4 7 8 2 6 5
Step = 5 -0 1 3 4 7 8 2 6 5
Step = 6 -0 1 2 3 4 7 8 6 5
Step = 7 -0 1 2 3 4 6 7 8 5
Step = 8 -0 1 2 3 4 5 6 7 8
Fig (4.9) insertion sort
Insertion_sort ( l, n )
Where l - Represents the list of elements.
n - Represents number of elements in the list.
Step 1: [Initialize]
l[0] = -0
Step 2: Repeat through Step 3 to 5 for i = 1, 2, 3, 4,***n
Step 3: (i) temp = l [i]
(ii) pointer = i l
Step 4: while ( temp < l [pointer] )
(i) l [pointer + l] = l [pointer]
(ii) pointer = pointer l
Step 5: l [pointer] = temp
Step 6: Exit
Fig (4.10) Algorithm for Insertion sort
For smaller values of n this algorithm is useful. The inner loop of the algorithm performs i-1
comparisons. Hence
n
i 1E(n) =
i=1
=> 1+2+3+4+..+n 1
=> n(n-1)/2
=> O(n2)
For average case the inner loop performs (i-l) /2 comparisons.
n
E(n) = (i-1) /2
i=1
=> ( 1+2+3+4+..+n-l ) /2
=> n(n-l) /4
=> O (n2)
Fig (4.9) illustrates the algorithm given in Fig (4.10).
The program segment INSERT.C implements the above discussion.
/* Insertion sort */
/* INSERT.C */
# include<stdio .h>
# include<stdlib.h>
int i, k;
void insertion_sort (int *, int );
void display (int*, int);
void insertion_sort (int l[], int n)
{
int pointer, temp;
l [0] = -0;
for (i =l); i < = n; i + +)
{
pointer = i l;
temp = l[i];
while (temp < l [pointer])
{
l [pointer + l] = l [pointer];
pointer -;
}
l [pointer + l] = temp;
printf ( Step = %d, i);
for (k = 0; k < = n; k + +)
printf ( %d, l [k]);
printf (\n);
}
}
void display ( int l [], int n)
{
printf (\n Sorted list is as follows\n);
for ( i = l; i < = n; i + +)
printf (%d, l [i]);
}
void main ( )
{
int number =10;
int list [100] ;
int i ;
printf (\n Number of elements in the list: %i, number) ;
printf (\n Unsorted list is as follows \n) ;
for (i = l ; i < = number ; i + +)
{
list [i] = rand ( ) % 100 ;
printf ( %d, list [i]) ;
}
printf (\n) ;
printf (\n Stepwise result is as follows \n\n ;
insertion_sort (list , number );
display (list, number) ;}
Another way of implementation of above technique is given below :
/*INSERS.C */
/* INSERTION SORT */
/* INSERS.C */
# include<stdio.h>
# include<stdlib.h>
int key;
int insertion_sort(int *);
// prototype
void display(int *, int);
/* Definition of the insertion sort function */
int insertion_sort(int list[])
{
int i = 0;
int j, k ;
printf("\nElement to be inserted Break condition is -0 : ");
scanf("%d", &key);
printf("\n Selected Element is: %d", key);
while(key != -0 ) /* -0 is break condition */
{
k = i - 1;
while((key < list[k]) && (k >= 0))
{
list[k+1] = list[k];
--k;
}
list[k+1] = key ;
printf("\n List after inserting an element ");
for(j = 0 ; j<=i; j++)
printf(" %d", list[j]);
printf("\n Element to be inserted Break condition is -0: ");
scanf("%d", &key);
printf("\n Selected Element is: %d", key);
i ++;
}
return i;
}
/* End of the insertion sort function */
/* Definition of the function */
void display(int list[], int n)
{
int j;
printf("\n Final sorted list is as follows:\n");
for(j = 0 ; j < n ; j++)
printf(" %d", list[j]);
}
/* End of the display function */
void main()
{
int list[200];
int n ;
n = insertion_sort(list);
display(list,n);
}
QUICK SORT
Quick sort treats an array as a list of elements. When sort begins it selects the lists middle
elements as the list pivot. The sort then divides the list into two sub-lists one with elements that
are less than the list pivot and second list with elements greater than or equal to the list pivot.
The sort then recursively invoke itself with both lists. Each time when the sort is invoked it further
divides the elements into smaller sub-lists.
Q-sort (array, first, last)
Represents the list of elements.Where array
Representsfirst the position of the first element in the list (Only at
the starting point, its value changes during the execution of the function).
last Represents the position of the last element in the list (only at
point the value of its changes during the execution of the function).
Step 1: [Initially]
low =first
high =last
pivot =array [ (low + high)/2 ] [Middle element of the element of the
List]
Step 2: Repeat through Step 7 while (low< high )
Step 3: Repeat Step 4 while (array [low] < pivot)
Step 4: low = low + 1
Step 5: Repeat Step 6 while (array [high] > pivot)
Step 6: high = high 1
Step 7: if ( low < high )
(i) temp = array [low]
(ii) array [low] = array [high]
(iii) array [high] = temp
(iv) low = low + 1
(v) high = high 1
Step 8: if (first < high) Q_sort ( array, first, high )
Step 9: if (low < last) Q_sort ( array, low, last )
Step 10: exit
Fig (4.12) Algorithm of Quick Sort
If partition process involves n comparisons with the pivot, with at most n/2 swaps and, hence, is If
the pivot is`O(n). The question, then is how many partitions are performed such that then array is
divided into two sub-arrays of the same size, then the situation is similar to merge sort. In this
case, the algorithm is O (n log n). However, in the worst case, each partitioning will divide the
array into parts of size 1 and n-1. Partition would then be called n times, with array sizes ranging
from 1 to n. The average case performance for quick sort algorithm is
O ( n log n ).
The following program segment implements the quick sort technique (quick.c)
/* quick.c */
#include <stdio.h>
#include <stdlib.h>
void quick_sort(int array[], int first, int last)
{
int temp, low, high, list_separator;
low = first;
high = last;
list_separator = array[(first + last) / 2];
do {
while (array[low] < list_separator)
low++;
while (array[high] > list_separator)
high--;
if (low <= high)
{
temp = array[low];
array[low++] = array[high];
array[high--] = temp;
}
} while (low <= high);
if (first < high)
quick_sort(array, first, high);
if (low < last)
quick_sort(array, low, last);
}
void main(void)
{
int values[100], i;
printf("\n Unsorted list is as follows \n");
for (i = 0; i < 20; i++)
{
values[i] = rand() % 100;
printf(" %d", rand() %100);
}
quick_sort(values, 0, 19);
printf("\n Sorted list as follows\n");
for (i = 0; i < 20; i++)
printf("%d ", values[i]);
}
SELECTION SORT
The selection sort starts from first element and searches the entire list until it finds the minimum
value. The sort places the minimum value in the first place, selects the second element and
searches for the second smallest element. The process continues until the complete list is sorted.
From the algorithm given in Fig (4.13), it is clear that the algorithm consumes most of its time in
the inner loop. During the pass current of the outer loop size current elements are examined to
find smallest remaining elements. This requires size current 1 comparisons.
The number of comparisons for all passes is:
Size-1
(size E (n) = current 1)
current
Let k = size current 1
k = size 1 at current = 0
k = 0 at current = size 1
Size-1
kE (n) =
k=0
size(size 1)/2
n(n 1)/2 Let size = n
O( n2)
Following program segment implements the discussion. (select.c)
/* select.c */
/* selection sort */
#include <stdio.h>
#include <stdlib.h>
void selection_sort(int array[], int size)
{
int temp, current, j;
for (current = 0; current < size; current++)
for (j = current + 1; j < size; j++)
if (array[current] > array[j])
{
temp = array[current];
array[current] = array[j];
array[j] = temp;
}
}
void main(void)
{
int values[30], i;
printf("\n Unsorted list is as follows \n");
for (i = 0; i < 30; i++)
{
values[i] = rand() % 100;
printf(" %d", rand() %100);
}
selection_sort(values, 30);
printf("\n Sorted list is as follows \n");
for (i = 0; i < 30; i++)
printf("%d ", values[i]);
}
Another way to illustrate the algorithm of selection sort.
/* SELECTION SORT */
/* selects.c */
# include<stdio.h>
int selection_sort(int , int *); /* Prototype */
void main()
{
int number, list[200];
int i;
printf("Input the number of elements in the list:");
scanf("%d", &number);
printf("\n Number of elements in the list is: %d", number);
printf("\nInput the elements of the list\n");
for(i = 0 ; i < number ; i++)
scanf("%d", &list[i]);
selection_sort( number, list);
}
/* Definition of function */
int selection_sort(int n, int l[])
{
int min ;
int k, index;
for(index = 0; index< n - 1 ; index++)
{
min = index ;
for(k = index + 1; k < n ; k ++)
{
if(l[min] > l[k])
min = k ;
}
if( min != index)
{
int temp = l [index];
l[index] = l[min];
l[min] = temp ;
}
}
printf("\n Entered list is as follows:\n");
for( index = 0 ; index < n; index++)
printf(" %d", l[index]);
return 0;
}
MERGE SORT
Suppose an array A with n elements A[1], [2], ., A[N] is in memory. The merge-sort algorithm
which sorts A will first be described by means of a specific example.
EXAMPLE 4.7
Suppose the array A contains 14 elements as follows:
66, 33, 40, 22, 55, 88, 60, 11, 80, 20, 50, 44, 77, 30
Each pass of the merge-sort algorithm will start at the beginning of the array A and merge pairs of
sorted subarrays as follows:
Pass1: Merge each pair of elements to obtain the following list of sorted pairs:
33, 66 22, 40 55, 88 11, 60 20, 80 44, 50 30, 77
Pass 2: Merge each pair of pairs to obtain the following list of sorted quadruplets:
22, 33, 40, 66 11, 55, 60, 88 20, 44, 50, 80 30,77
Pass 3: Merge each pair of sorted quadruplets to obtain the following two sorted subarrays:
11, 22, 33, 40, 55, 60, 66, 88 20, 30, 44, 50, 77, 80
Pass 4: Merge the two sorted subarrays to obtain the single sorted array
11, 20, 22, 30, 40, 44, 50, 55, 60, 66, 77, 80, 88
The original array A is now sorted.
The above merge sort algorithm for sorting an array A has the following important property. After
Pass K, the array A will be partitioned into sorted subarrays where each subarray, except possibly
the last, will contain exactly L=2k elements. Hence the algorithm requires at most log n passes to
sort an n-element array A.
The formal statement of the merge sort algorithm follows:
Algorithm MERGESORT (A, N)
This algorithm sorts the N element array A using an auxiliary array B.
1. Set L: =1. [Initializes the number of elements in the subarrays.]
2. Repeat Steps 3 to 6 while L<N:
3. Call MERGEPASS (A, N, L, B).
4. Call MERGEPASS (B, N, 2*L, A).
5. Set L: = 4 * L.
[End of Step 2 loop.]
6. Exit.
Complexity of the Merge Sort Algorithm
Let f(n) denote the number of comparisons needed to sort an n element array A using the merge
sort algorithm. Recall that the algorithm requires at most log n passes. Moreover, each pass
merges a total of n elements, and by the discussion on the complexity of merging, each pass will
require at most n comparisons. Accordingly, for both the worst case and average case,
n logf(n) n
Observe that this algorithm has the same order as heapsort and the same average order as
quicksort. The main drawback of merge-sort is that it requires an auxiliary array with n elements.
Each of the other sorting algorithms we studied requires only a finite number of extra locations,
which is independent of n.
The above results are summarized in the following table:

Algorithm Worst Case Average Case Extra Memory
Merge-Sort n log n = O (n log n) n log n = O (n log n) O (n)
Program to illustrate the merge sort
/* MERGE SORT */
/* merge.c */
# include<stdio.h>
# include<stdlib.h>
void merge_sort(float *, int , int , int );
void merge_pass(float *, int , int );
/* Definition of the function */
void merge_sort(float l[], int top, int size, int bottom)
{
float temp[1000];
int f = top;
int s = size +1 ;
int t = top ;
int upper;
while(( f <= size)&&(s <=bottom))
{
if(l[f] <= l[s])
{
temp[t] = l[f] ;
f ++;
}
else
{
temp[t] = l[s] ;
s ++;
}
t ++;
}
if(f <=size)
{
for(f = f ; f<=size; f++)
{
temp[t] = l[f];
t++;
}
}
else
{
for(s = s ; s<= bottom ; s++)
{
temp[t]=l[s];
t++;
}
}
for(upper = top; upper <= bottom ; upper++)
{
l[upper]=temp[upper];
}
}
/* Definition of the function */
void merge_pass( float append[], int m, int n )
{
if( m!= n)
{
int mid = (m+n)/2;
merge_pass( append, m, mid );
merge_pass( append, mid+1, n );
merge_sort( append, m, mid, n );
}
}
/* main function */
void main()
{
float list[1000];
int i, n = 30;
printf("\n Size of the list: %d", n);
for(i = 0 ; i < n ; i++)
{
list[i] = (float) (rand() %100);
}
printf("\n Entered list as follows:\n");
for( i = 0 ; i<n ; i++)
printf(" %d ", (int) list[i]);
i = 0 ;
merge_pass(list, i, n-1);
printf("\n Merge sorted list is as follows:\n");
for( i = 0 ; i<n ; i++)
printf(" %d", (int) list[i]);
}
RADIX SORT
Radix sort is a technique, which is usually used when large lists of names are to be sorted
alphabetically. Using this sorting technique one can classify the list of names into 26 groups. The
list is first sorted on the first letter of each name, i.e., the names are arranged in 26 classes where
the first class consists of those names that begin with alphabet A, the second class consists of
those names that begin with alphabet B and so on. During the second pass each is alphabetized
according to the second letter of the name and so on. For e.g., if no name contains more than 20
characters then the sort requires 20 passes. The radix sort is a technique, which is used by a card
sorter. A card sorter contains 13 receiving pockets labeled as
9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 11, 12, R
Here R represents reject, if any card comes in this pocket.
Each pocket other R corresponds to a row on a card in which a hole can be punched. Decimal
numbers where the radix is 10 are punched in the obvious way and hence use only the first 10
pockets on the sorter. The sorter uses a radix reverse digit sort on numbers. For e.g., suppose a
card sorter is given a collection of cards where each card contains a four- digit number punched in
columns 1 4. The cards are first sorted according to the units digit. In the second pass, the cards
sorted according to the tens digit. In the third pass the cards are sorted according to the hundreds
digit. In the fourth and last pass, the cards are sorted according to the thousands digit. For e.g.,
suppose cards are punched as shown in the Fig.

1 2 3 4 5 6 7
4348 2143 4361 5423 4538 2128 5438
Fig. (A) Punched card data
Fig (A.1)Pass 1 sort units digit
(i) Pass 1: The unit digits are sorted into pockets. The cards are collected pocket by pocket from
pocket 9 to pocket 0. The cards are now re- input to the sorter.
(ii) Pass 2: The tens digit are sorted into pockets. Again cards are collected pocket by pocket and
re- input to the sorter.
Fig.(A.2) Pass 2 sort on 10th digit
(iii) Pass 3: The 100th digits are sorted into pockets. Again cards are collected pocket by pocket
and re- input to the sorter.
Fig. (A.3) Pass 3 sort on 100th digit
(iv) Pass 4: The 1000s digits are sorted into pocket. Again cards are sorted pocket by pocket.
Fig. (A.4) Pass 4 sort on 1000s digit
Now collecting the values of pockets from 9th to 0th then we get the list of array as shown in Fig.
(B)

1 2 3 4 5 6 7
5438 5423 4538 4361 4348 2143 2128
Fig. (B) Sorted list using radix sort
From the result shown in Fig (B) , it it clear that the list is sorted in descending order.
Fig (C.1)Pass 1 sort units digit
Fig.(C.2) Pass 2 sort on 10th digit
Fig.(C.3) Pass 3 sort on 100th digit
Fig.(C.4) Pass 4 sort on 1000th digit
If during the sorting operation one collects the pocket from 0th to 9th the result will come in
ascending order. For example , Fig .(C.1 C.4) illustrates the preceding statement.
Now collecting the values of pockets from 0th to 9th , we get the list of array as shown in fig D.

1 2 3 4 5 6 7
2128 2143 4348 4361 4538 5423 5438
Fig .D Sorted list using Radix Sort.
The result shown in Fig. D denotes that the list is sorted in ascending order.
In general we can define an algorithm for radix sort as follows:
Step 1: Repeat through Step 6 for each digit in the key.
Step 2: Initialize the pockets.
Step 3: Repeat through Step 5 until end of the linked list.
Step 4: Obtain the next digit of the key.
Step 5: Insert the element in appropriate pocket.
Step 6: Combine the pockets to form a new linked list.
Suppose rec represents a list of n elements, i.e., rec1, rec2, .,recn and d denotes the radix (For
decimal number system, which is 10, for alphabets it is 26, binary it is 2, for octal number system
it is 8 etc.) and each element reci is represented by means of m digits.
reci =di1 di2 di3 dim.
The radix sort algorithm requires m pass the number of digits in each element. Pass j will
compare each dij with each of the d digits. Hence, total number of comparisons (and in turn
efficiency) is:
E(n) = d*m*n [Maximum value possible that is possible]
Where d and m are independent of n.
(i) Worst case: If n = m the E(n) = d*n*n = d*n2O(n2)
(ii) Best case: m = logd n
E(n) =d*(logd n)*n
= O( n logd n)
Algorithm to find largest number in the list
Algorithm to find number of digits in largest number in the given list
Algorithm that make links elements during Sorting
Algorithm which updates the values of the pockets
The sub-algorithm, which are necessary in the radix sort, are given in the above algorithms.
pocket [i] Represents top element in the ith pocket
Represents bottompocket1 [i] element in the ith pocket.
Represents j pass j index.
Represents pocket i index.
Represents temporary index poc variable.
Represents a pointer variable which denotes the address of the current element begin examined
in the list and begin directed to appropriate pocket.
Represents a pointer variable which denotes the address of the next element to be examined in
the list and being directed to appropriate pocket.
Represents the current digit in a key being examined.
Algorithm for radix sort
Program segment RADIX.C implements the radix sort algorithm is illustrated below:
/* RADIX SORT */
/* RADIX.C*/
# include<stdio.h>
# include<malloc.h>
# include<stdlib.h>
struct node
{
int data ;
struct node *next;
};
typedef struct node node1;
node1 *first;
node1 *pocket[100], *pocket1[100];
void create_node(node1 *, int);
void display(node1 *);
node1 *radix_sort(node1 *);
int large(node1 * );
int numdig(int );
int digit(int , int);
void update(int, node1 *);
node1 *Make_link(int, node1 *);
/* This function create nodes and take input data */
void create_node(node1 *rec, int n)
{
int i, j, k;
for(i = 0 ; i< n; i++)
{
rec->next = (node1 *) malloc(sizeof(node1));
printf("\n First node value: %d: ", i);
scanf("%d", &rec->data);
rec = rec->next;
}
rec->next = NULL;
}
/* Output Function */
void display(node1 *rec)
{
while(rec !=NULL)
{
printf(" %d", rec->data);
rec= rec->next;
}
}
/* This radix sort function */
node1 *radix_sort(node1 *rec)
{
node1 *r, *nex;
int poc = 0 ;
int i, j, k;
int larg = large(rec);
int m = numdig(larg);
/* These statements create pockets */
for(k = 0 ; k < 10; k++)
{
pocket[k] = (node1 *)malloc(sizeof(node1));
pocket1[k] = (node1 *)malloc(9*sizeof(node1));
}
/* These statements initialize pockets */
for(j = 1; j <= m ; j++)
{
for(i = 0 ; i < 10 ; i++)
{
pocket[i] = NULL;
pocket1[i] = NULL ;
}
r = rec ;
while(r != NULL)
{
int dig = digit(r->data, j);
nex = r->next ;
update(dig,r);
r = nex;
}
if(r!= NULL)
{
int dig = digit(r->data,j);
update(dig,r);
}
while(pocket1[poc] == NULL)
poc ++;
rec = Make_link(poc, rec);
}
return(rec);
}
/* This function finds largest number in the list */
int large(node1 *rec)
{
node1 *save ;
int p = 0;
save = rec ;
while(save != NULL)
{
if(save ->data > p)
{
p = save->data;
}
save = save->next ;
}
printf("\n Largest element: %d", p);
return(p);
}
/* This Function finds number digits in a number */
int numdig(int large)
{
int temp = large ;
int num = 0 ;
while(temp != 0)
{
++num ;
temp = temp/10 ;
}
printf("\n Number of digits of the number %d is %d", large, num);
return(num);
}
/* This function scarve a number into digits */
int digit(int num, int j)
{
int dig, i, k;
int temp = num ;
for(i = 0 ; i < j ; i++)
{
dig = temp % 10 ;
temp = temp / 10 ;
}
printf(" %d digit of number %d is %d", j, num, dig);
return(dig);
}
/* This function updates the pockets value */
void update(int dig, node1 *r)
{
if(pocket[dig] == NULL)
{
pocket[dig] = r ;
pocket1[dig] = r ;
}
else
{
pocket[dig]->next = r ;
pocket[dig] = r ;
}
r->next = NULL;
}
/* This function create links between the nodes */
node1* Make_link(int poc , node1 *rec)
{
int i, j, k;
node1 *pointer;
rec = pocket1[poc];
for(i = poc +1 ; i< 10 ; i++)
{
pointer = pocket[i-1];
if(pocket[i] != NULL)
pointer->next= pocket1[i];
else
pocket[i] = pointer ;
}
return(rec);
}
/* Main function */
void main()
{
node1 *start, *pointer;
int number;
printf("\n Input the number of elements in the list:");
scanf("%d", &number);
start = (node1 *)malloc(sizeof(node1));
create_node(start, number);
printf("\n Given list is as follows \n");
display(start);
start = radix_sort(start);
printf("\n Sorted list is as follows:\n");
display (start);
}

Potrebbero piacerti anche