Notes
Notes
OF AIML
Module-1
Define Data:
Data item refers to single unit of values. Considering any employee, EID, Name, Phone No,
years_of__experience, designation are all examples of data.
Types of Data:
Data can be classified as grouped or elementary data based on the possibility of subdivision.
Grouped data can be further subdivided into components. Eg. Name of any employee can be
subdivided into First_Name, Middle_Name and Last_Name. However, elementary data cannot be
further subdivided. SSN or ID of any employee cannot be further subdivided and is an example for
Elementary data.
Each elementary data or component of a grouped data will have a data type.
Problem:
Identifiy the type of data for following:
(i)Aadhar_Card_Number (ii)Name (iii) Age (iv) Weight (v) Address
Solution:
(i) Aadhar_Card_Number - Elementary and Data Type: Long
(ii) Name: Grouped Data with components First_Name,
Middle_Name and Last_Name and data type is character array.
(iii) Age: Elementary Data and Data Type: Integer
(iv) Weight: Elementary Data and Data Type: Float
(v) Address: Grouped Data with components Street, City, State,
Country, Zip_Code and data type is character array.
Data vs Information:
Parameter Data Information
Definition Raw facts Data with context
Context required Not required as any value starts as Always required
data
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Some fields distinguish each record and uniquely define a record. Such fields are called key-fields.
Eg: A Student file can be created which captures records of each student in the college. Each student
record will have values for fields like USN, Name, Dept, Sem, and Sex. USN is unique for each
student and is considered as keyfield.
Examples If fields like USN, Sem and Sex is If field Name is used in for
used for Student file, then each Student file, then each Name
record is fixed-length as USN is variable-length and hence
occupies 10 chars, Sem is int, and also makes variable-length
Sex is 1charachter record file.
Problem:
In Hospital patient file: Name, Admission Date, Social Security Number, Room Number, Bed
Number, Doctor, identify primary key and identify each data item as grouped or elementary
with their types
Social Security Number is unique for each patient and hence can be a primary key
Name – Grouped data with components First_Name, Middle_Name and Last_Name with type
character array
Admission Date – Grouped data with components Day, Month and Year with type character array
Social Security Number – Elementary data with type unsigned long
Room Number – Elementary Data with type Integer
Bed Number – Elementary Data with type Integer
Doctor – Grouped data with components First_Name, Middle_Name and Last_Name with type
character array
Problem:
Which of following data items may lead to variable-length records when included as items in
the record:
(a) Age (b) Sex (c) Name of the spouse (d) Names of children (e) Education (f) Previous
employers
Linear Data Structures have concept of previous and next for any element. In case of arrays, element
at any index has previous at (index-1) and next at (index+1). For linked list, there is a link from one
element to next element. It is called linear due to contiguous organization in memory. In case of non-
linear data structures elements are not connected linearly (contiguously) and exhibit hierarchical
relationship.
Linked List:
Linked List is a data structure where each element is connected through other element using pointers.
If there are set of elements, one element is connected to another in a sequence and last element is
connected to NULL.
Realword example:
Consider the following file containing customer and the handling sales person:
One way of organizing is use an array for sales person and pointer in the customer file
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Problem with this approach is, if one needs to find all customers of a given sales person, they need to
completely traverse the customer file which is highly inefficient when volume of records increases.
Second way of organizing is use an array for sales person and pointer to customers
Problem with this approach is, that whenever a new customer is added, pointers maintained in
salesperson should be changed. Further whenever an existing customer is deleted, pointers need to be
removed. The pointer manipulation is a complex operation and hence not efficient.
Hence most efficient way of organization is to use Linked List as shown below:
This approach provides advantages like (i) need not traverse entire customer file for searching records
and (ii) multiple pointers need not be maintained which is efficient. Hence it overcomes the
drawbacks of both previous array based approaches.
Problem:
Write a tree for:
Employee (SSN, Name, Address, Age, Salary)
Solution:
This is a 4 level tree. Each subdivision of a field creates a level in the tree.
Problem:
Write a tree for:
(2*x+y)*((a-7*b)^3)
Solution:
While writing tree for expressions, BODMAS rule is used as priority. B-Brackets, O-Order (power),
D-Division, M-Multiplication, A-Addition and S-Subtraction.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
(vi) Sorting – Operation for arranging set of elements in increasing (ascending) or decreasing
(descending) order.
(vii) Merging – An operation for joining the elements of one set to another.
Problem:
Gym center maintains membership file which contains following information (Name, Address,
TelephoneNumber, Age, Sex). Demonstrate all possible operations : Searching, Traversing,
Insertion, Deletion, Updation, Sorting and Merging
Solution:
Searching – search for Gym members based on Name or Address or Age or combination of many
fields.
Traversing – visit all members from beginning to end stored in the membership file one by one.
Insertion – Add a new member to the Gym
Deletion – Remove an existing member from Gym.
Updation – update the profile of a given member in the Gym
Sorting – Order the members in the Gym in the alphabetical order of Names
Merging – In case Gym has multiple centers, merge records of each file maintained into a single file.
Strings:
Strings are defined as sequence (array) of characters. In C, strings data type does not exist, rather it a
character array. In C, all strings are null terminated. Strings are constructed from characters in the
character set. Character set followed in C is ASCII (American Standard Code for Information
Interchange). ASCII character set is made of alphabets (both upper and lower case), digits and special
characters(?,: etc).
Points on Strings:
A finite sequence of zero or more characters is called Strings.
String of zero length is called empty string and denoted by “”;
Characters are denoted by single quotes (‘A’) and strings are denoted by double quotes
(“AIML”)
String Operations:
- Concatenation: An operation in which second string is appended to the end of first string
Notation: S1//S2
Eg: “Hello/World”
- Substring: An operation in which existence of a string inside another string is checked.
Notation: X//Y//Z
Where Y is called substring.
If X is empty, Y is called initial substring
If Z is empty, Y is called terminal substring
- Eg: In a string “Artificial”, “Art” is an initial substring, “cial” is terminal substring and “ifi”
is a substring which is neither initial not terminal substring.
- Size of a character in C is 1 byte which is found by calling sizeof(char)
Eg:
Solution is to maintain a separate POINT array. Whenever new record is added, POINT array
can be updated to point to the suitable record.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
In this example, new record int x; has to be added before printf, This can be adjusted in the
POINT array without updating original record lines.
Using lengths
But with this kind of storage, since fixed maximum is used, space is still wasted when record length
is very less than fixed maximum. Hence solution is to use variable length storage with markers and
variable size. Such an example is shown below:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Hence each record can accommodate any number of lines and each occurrence of $$ marks one
record.
String operations:
- SUBSTRING(string, initial, length)
Extracts a substring from main string, starting at initial position till number of characters
defined by length parameter.
Eg: SUBSTRING(“PANIPURI”,3,3) => “NIP”
SUBSTRING(“QUEUE”,2,8)=> “UEUE”
- INDEX(string, pattern)
Checks whether pattern is available in the string. If found, returns location of starting character
in the pattern. If multiple occurences of same pattern exists, location of first occurrence is
returned. If the pattern does not exist, 0 is returned.
Eg: INDEX(“GOBIMANCHURI”, “MAN”) => Returns 5
INDEX(“QUEUE”, “UE”) => Returns 2
INDEX(“GOBIMANCHURI”, “WOMAN”) => Returns 0
- LENGTH(STRING)
Returns the number of characters in the String
Eg: LENGTH(“SAMSUNG”) returns 7
Tracing:
1. T-“JAMBOON”, P-“BOON”
S- LENGTH(T)=7
R- LENGTH(P)=4
2. T-“JAMBOON”, P-“BONE”
S- LENGTH(T)=7
R- LENGTH(P)=4
Eg: P=aaba
Construction of Pattern matching table:
State a b x
QO Q1 QO QO
Q1 Q2 QO QO
Q2 Q2 Q3 QO
Q3 P QO QO
(ii) T=abcaabaca
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Algortihm:
Knuth-Morris-Pratt Algorithm
KMP Algorithm is one of the most popular patterns matching algorithms. KMP stands for Knuth
Morris Pratt. KMP algorithm was invented by Donald Knuth and Vaughan Pratt together and
independently by James H Morris in the year 1970. In the year 1977, all the three jointly published
KMP Algorithm. KMP algorithm was the first linear time complexity algorithm for string matching.
KMP algorithm is used to find a "Pattern" in a "Text". This algorithm compares character by
character from left to right. But whenever a mismatch occurs, it uses a preprocessed table
called "Prefix Table" to skip characters comparison while matching. Some times prefix table is also
known as LPS Table. Here LPS stands for "Longest proper Prefix which is also Suffix".
Eg:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Linear Arrays:
Linear Arrays are a list of finite number of n homogeneous elements such that:
(a) Elements referred by index of n consecutive numbers
(b) Elements stored in contiguous memory allocation
Eg: int a[4] is a linear array as:
it is finite (4 elements), homogeneous as each element is integer, referred by index set {0,1,2,3} and
allocated contiguously in stack. If array a starts with address 1012, next element will be at 1016, then
1020 and last element at 1024.
Further, for linear arrays, concept of subscript and subscripted variables exists.
In case of int a[4], one can access third element of an array as a[2].
Here 2 is the subscript and a[2] is called subscripted variable.
malloc() function in C
The malloc() function allocates single block of requested memory. It doesn't initialize memory
at execution time, so it has garbage value initially. It returns NULL if memory is not sufficient.
The syntax of malloc() function is given below:
ptr=(cast-type*)malloc(byte-size)
Eg:
ptr=(int *)malloc(sizeof(int)*5); //Allocates 5 blocks of integers and returns pointer to first
block and all blocks contain garbage.
calloc() function in C
The calloc() function allocates multiple block of requested memory. It initializes all bytes to
zero. It returns NULL if memory is not sufficient.
The syntax of calloc() function is given below:
ptr=(cast-type*)calloc(number, byte-size)
Eg:
ptr=(int *)calloc(5,sizeof(int)); //Allocates 5 blocks of integers and returns pointer to first
block. Further all blocks are set to NULL
realloc() function in C
If memory is not sufficient for malloc() or calloc(), you can reallocate the memory by realloc()
function. In short, it changes the memory size.
Let's see the syntax of realloc() function.
ptr=realloc(ptr, new-size)
Eg:
ptr=(int *)ralloc(ptr,sizeof(int)*7); //Resizes ptr to contain 7 blocks of memory
free() function in C
The memory occupied by malloc() or calloc() functions must be released by calling free() function.
Otherwise, it will consume memory until program exit.
Let's see the syntax of free() function.
free(ptr)
Step 5: Return
#include<stdio.h>
void create_array(int *arr,int n)
{
printf("Enter %d array elements one by one\n",n);
int i;
for(i=0;i<n;i++)
{
scanf("%d",&arr[i]);
}
}
void main()
{
int choice,n,sum,min;
int *arr;
while(1)
{
printf("***********Array Menu Operations*******\n");
printf("1. Create\n");
printf("2. Display\n");
printf("3. Exit\n");
printf("Enter your choice\n");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("Create an array\n");
printf("Enter the value of n\n");
scanf("%d",&n);
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
arr=malloc(sizeof(int)*n);
create_array(arr,n);
break;
case 2:printf("Display the array\n");
display_array(arr,n);
break;
case 3:exit(0);
default:printf("Enter 1 2 or 3\n");
}
}
}
2. Bubble Sort
Algorithm:
Step 1: Start
Step 2: Initialize an array ARR of ‘N’ elements
Step 3: For I=0 to N-1 //Passes
Step 3.1: FOR J=0 to N-1-I //Comparisons
Step 3.1.1: IF ARR[J] > ARR[J+1]
SWAP ARR[J] and ARR[J+1]
Step 4: FOR I=0 to N-1
Step 4.1 PRINT ARR[I]
Step 5: Return
C Program:
#include<stdio.h>
void main()
{
int a[5]={1,3,2,4,0};
int N=5,i,j,t;
//Loop for passes
for(i=0;i<N-1;i++)
{
//Loop for comparisons
for(j=0;j<N-i-1;j++)
{
//Check for swapping
if(a[j]>a[j+1])
{
//Do swapping
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
}
}
}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
3. Linear Search
Algorithm:
Step 1: Start
Step 2: Initialize an array ARR of ‘N’ elements
Step 3: Read key KEY from the user
Step 4: For I=0 to N-1 //Searching Loop
Step 4.1: IF ARR[I]==KEY THEN
PRINT “SUCCESSFUL SEARCH”
RETURN
Step 5: PRINT “UNSUCCESSFUL SEARCH”
Step 6: Return
C Program:
#include<stdio.h>
void main()
{
int a[5]={1,3,2,4,0};
int KEY,i,N=5;
printf("Enter the key\n");
scanf("%d",&KEY);
//Loop for passes
for(i=0;i<N;i++)
{
if(a[i]==KEY)
{
printf("Succesful Search\n");
exit(0);
}
}
printf("Unsuccesful Search\n");
}
Multidimensional Arrays:
Multidimensional Arrays are the linear arrays with number of dimensions more than 1. Few examples
are matrix of 2 dimension (with rows and columns), image of 3 dimension (channels, rows, columns),
video of 4 dimension (frame, channels, rows, columns).
Representation of 2D Arrays in memory:
There are 2 representations: Row-major order and Column-major order.
In the row-major order, the elements are stored row by row. First row elements are filled,
subsequently second row elements till last row.
In the column-major order, the elements are stored column by column. First column elements are
filled, subsequently second column elements till last column.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Eg:
Programs/Algorithms on 2D Arrays:
1. Creating 2D array statically, reading input from keyboard, displaying matrix and
computing trace
Algorithm:
Step 1: Start
Step 2: Create 2D array MAT with size M and N
Step 3: FOR I=0 to M-1
Step 3.1: FOR J=0 to N-1
Step 3.1.1: Read element from keyboard and store into MAT[I][J]
Step 4: FOR I=0 to M-1
Step 4.1: FOR J=0 to N-1
Step 4.1.1: PRINT MAT[I][J]
Step 5: FOR I=0 to M-1
Step 5.1: SUM=SUM+ MAT[I][I]
Step 6: PRINT SUM
Step 7: Return
C Program:
#include<stdio.h>
void main()
{
int M=3,N=3;
int mat[M][N],i,j;
int sum=0;
printf("Enter the matrix elements\n");
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
scanf("%d",&mat[i][j]);
}
}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
printf("Matrix:\n");
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
printf("%d ",mat[i][j]);
}
printf("\n");
}
for(i=0;i<M;i++)
{
sum=sum+mat[i][i];
}
printf("Trace of matrix=%d\n",sum);
2. Creating 2D array dynamically, reading input from keyboard, displaying matrix and
computing trace
Algorithm:
Step 1: Start
Step 2: Get M (no of rows) and N (no of cols) from user
Step 3: Create a pointer to point to a pointer array MAT
Step 4: FOR I=0 to M-1
Step 4.1: Allocate memory for each element of MAT[i]
C Program:
#include<stdio.h>
void main()
{
int **mat,i,j,M,N;
printf("Enter the value of M and N\n");
scanf("%d%d",&M,&N);
mat=malloc(sizeof(int*)*M);
for(i=0;i<M;i++)
{
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
mat[i]=malloc(sizeof(int)*N);
}
int sum=0;
printf("Enter the matrix elements\n");
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
scanf("%d",&mat[i][j]);
}
}
printf("Matrix:\n");
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
{
printf("%d ",mat[i][j]);
}
printf("\n");
}
for(i=0;i<N;i++)
{
sum=sum+mat[i][i];
}
printf("Trace of matrix=%d\n",sum);
Algorithm:
Step 1: Start
Step 2: Set M to no of rows and N to no of cols
Step 3: Create a pointer to point to a pointer array MAT
Step 4: FOR I=0 to M-1
Step 4.1: Allocate memory for each element of MAT[i]
#include<stdio.h>
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
void main()
{
int **mat;
int i,j,m=3,n=2;
mat=malloc(sizeof(int*)*m);
for(i=0;i<m;i++)
{
mat[i]=malloc(sizeof(int)*n);
}
printf("Enter the matrix values one by one\n");
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&mat[i][j]);
}
}
printf("Transpose of matrix\n");
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
printf("%d ",mat[j][i]);
}
printf("\n");
}
}
Address computation of an array element:
Address of any element of an array can be computed using formulae:
scanf(“%d”,&a[i]);
void main()
{
int i;
int a[]={1,2,3,4,5,6,7,8};
int b[8];
for(i=0;i<8;i++)
{
b[i]=a[i]; //Copying code
}
for(i=0;i<8;i++)
printf("%d\n",b[i]);
}
Write a C program to demonstrate selective copying of an array
#include<stdio.h>
void main()
{
int i;
int a[]={1,2,3,4,5,6,7,8};
int b[4],j=0;
for(i=0;i<8;i++)
{
if(a[i]%2==0) //Only copy Even number
{
b[j++]=a[i];
}
}
for(i=0;i<4;i++)
printf("%d\n",b[i]);
Jagged Arrays:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
A double pointer can be created in stack which can point to Pointer Arrays. Each pointer in the
pointer array can point to arrays of variable size. An array in which each row contains variable number
of columns is called “Jagged Arrays”.
}
for(i=0;i<4;i++)
{
for(j=0;j<=i;j++) // j depends on i
{
jag[i][j]='*';
}
}
for(i=0;i<4;i++)
{
for(j=0;j<=i;j++)
{
printf("%c ",jag[i][j]);
}
printf("\n");
}
}
#include<stdio.h>
void main()
{
char **jag; //Jagged Array
int i,j;
jag=malloc(sizeof(char*)*4); //Allocate memory for rows
for(i=0;i<4;i++)
{
jag[i]=malloc(sizeof(char)*(i+1)); //Allocate memory for columns of each row
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
}
for(i=0;i<4;i++)
{
for(j=0;j<=i;j++) // j depends on i
{
jag[i][j]='*';
}
}
for(i=0;i<4;i++)
{
for(j=0;j<=i;j++)
{
printf("%c ",jag[i][j]);
}
printf("\n");
}
}
Structures:
Structures are collection of heterogeneous elements. Arrays are collection of homogeneous
elements. Heterogeneity of structures is with respect to different type of data packed in a structure.
Eg:
struct person
{
char name[10];
int age;
float salary;
};
Here person is called tag of structure and name, age and salary are called fields.
Hence a structure in this example holds different types of data like character array, integer and floating
point.
Note: while computing the size of structure, for a character array take size in multiple of word
boundary (multiple of 4)
#include<stdio.h>
typedef struct
{
char name[20];
int age;
float salary;
}person;
Write a C program to create an array of 3 persons, read the data and print the same – Use
static allocation
#include<stdio.h>
typedef struct
{
char name[20];
int age;
float salary;
}person;
void main()
{
int i;
person p[3]; //Static allocation by Declaration
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Write a C program to create an array of n persons, read the data and print the same – Use
dynamic allocation.
#include<stdio.h>
typedef struct
{
char name[20];
int age;
float salary;
}person;
void main()
{
int i,n;
printf("Enter the value of n \n");
scanf("%d",&n);
person *p; //Declaration
p=malloc(sizeof(person)*n);
//Read the data
printf("Enter details of %d person\n",n);
for(i=0;i<n;i++)
{
scanf("%s%d%f",p[i].name,&p[i].age,&p[i].salary);
}
//Print the data
for(i=0;i<n;i++)
{
printf("%s,%d,%f\n",p[i].name,p[i].age,p[i].salary);
}
free(p);//Ensures no garbages are created
}
Nested Structures:
One can put a structure inside another and this concept is called Nested structures.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Previous program can be modified with person structure containing a structure for date of
birth as follows:
#include<stdio.h>
typedef struct
{
int day;
int month;
int year;
}dob;
typedef struct
{
char name[20];
int age;
float salary;
dob d; //Since aliased dob can be directly used instead of struct dob
}person; //Person is a nested structure containing DOB
void main()
{
int i,n;
printf("Enter the value of n \n");
scanf("%d",&n);
person *p; //Declaration
p=malloc(sizeof(person)*n);
//Read the data
printf("Enter details of %d person\n",n);
for(i=0;i<n;i++)
{
scanf("%s%d%f%d%d%d",p[i].name,&p[i].age,&p[i].salary,
&p[i].d.day,&p[i].d.month,&p[i].d.year);
}
//Print the data
for(i=0;i<n;i++)
{
printf("%s,%d,%f,%d,%d,%d\n",p[i].name,p[i].age,p[i].salary ,
p[i].d.day,p[i].d.month,p[i].d.year);
}
void main()
{
list *l1,*l2,*l3;
l1=malloc(sizeof(list));
l2=malloc(sizeof(list));
l3=malloc(sizeof(list));
l1->data=20;
l1->next=l2;
l2->data=40;
l2->next=l3;
l3->data=10;
l3->next=NULL;
Here structure list contains a pointer next which refers to structure list itself and hence the structure
is called Self Referential structure. Further this structure represents one node and multiple nodes (l1,
l2,l3) is created. Dynamically memory is allocated for each node. The pointers create a link between
nodes and resulting structure is called linked list.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
First row corresponds to number of rows, number of columns and number of non-zero elements. Rest
of the rows are filled row-wise and in each row column-wise. Only non-zero elements are considered
and for each non-zero element, row index, column index and value is recorded.
Using this sparse storage, transpose can be computed by copying from first entry of sparse storage
with row and column values being swapped. Then from subsequent entries in sparse storage, lowest
column number is found. For each such entry, row and column indices are swapped, value is retained
in an entry created in transpose. For the example discussed above, corresponding transpose is:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Fast transpose is computed by finding position of each column index using startingpos array. Then
row and column values are swapped and value entry of column index in sparse storage is copied to a
position in the fast transpose array indicated by startingpos value.
{
scanf("%d",&mat[i][j]);
}
}
}
void print_matrix(int mat[10][10],int m,int n)
{
int i,j;
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
printf("%d ",mat[i][j]);
}
printf("\n");
}
}
}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
b[j].row=a[i].col;
b[j].col=a[i].row;
b[j].value=a[i].value;
j++;
}
}
void main()
{
int mat[10][10],m,n,nzi;
term a[10],b[10];
m=3,n=4;
read_matrix(mat,m,n);
print_matrix(mat,m,n);
nzi=create_sparse(mat,m,n,a);
display_sparse(a,nzi);
transpose_sparse(a,b);
printf("TRanspose.....\n");
display_sparse(b,nzi);
fast_transpose(a,b);
printf("Fast TRanspose.....\n");
display_sparse(b,nzi);
Implementation using C:
#include<stdio.h>
#define MAXTERMS 10
typedef struct
{
int degree;
int coeff[MAXTERMS];
} polynomial;
//Zeroing a polynomial
polynomial Zero(polynomial p)
{
int i;
p.degree=0;
for(i=0;i<MAXTERMS;i++)
p.coeff[i]=0;
return p;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
//Attach
polynomial attach(polynomial p, int e, int c)
{
p.coeff[e]=c;
return p;
}
//Detach
polynomial detach(polynomial p, int e)
{
p.coeff[e]=0;
return p;
}
//Adding 2 polynomials
polynomial add(polynomial a, polynomial b, polynomial c)
{
int sum;
c.degree=leadExp(a)>leadExp(b)?leadExp(a):leadExp(b);
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
//Displaying polynomial
void display(polynomial p)
{
int i;
for(i=p.degree;i>=0;i--)
{
printf("%dx^%d +",p.coeff[i],i);
}
printf("\b \n");
}
void main()
{
polynomial a,b,c;
a=Zero(a);
a.degree=2;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
a.coeff[2]=4;
a.coeff[1]=6;
a.coeff[0]=1;
b=Zero(b);
b.degree=1;
b.coeff[1]=5;
b.coeff[0]=5;
display(a);
display(b);
c=add(a,b,c);
display(c);
}
Structure to be used:
Filling of Polynomial A:
Filling of Polynomial B:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Implementation using C:
#define MAXTERMS 100
typedef struct
{
float coeff;
int expon;
}polynomial;
polynomial terms[MAXTERMS];
int startA,startB,finishA,finishB,avail=0;
terms[avail].coeff=coeff;
terms[avail].expon=exp;
avail++;
}
void add(int startA,int finishA, int startB, int finishB, int *startD, int *finishD)
{
float sum;
avail=finishB+1;
*startD=avail;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
while((startA<=finishA)&& (startB<=finishB))
{
if(terms[startA].expon>terms[startB].expon)
{
attach(terms[startA].coeff,terms[startA].expon);
startA++;
}
else if(terms[startA].expon<terms[startB].expon)
{
attach(terms[startB].coeff,terms[startB].expon);
startB++;
}
else
{
float sum=terms[startA].coeff+terms[startB].coeff;
attach(sum,terms[startA].expon);
startA++;
startB++;
}
}
while((startA<=finishA))
{
attach(terms[startA].coeff,terms[startA].expon);
startA++;
}
while((startB<=finishB))
{
attach(terms[startB].coeff,terms[startB].expon);
startB++;
}
*finishD=avail-1;
}
}
printf("\b \n");
}
void main()
{
int startD,finishD;
terms[0].coeff=2;
terms[0].expon=1000;
terms[1].coeff=1;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
terms[1].expon=0;
terms[2].coeff=1;
terms[2].expon=4;
terms[3].coeff=10;
terms[3].expon=3;
terms[4].coeff=3;
terms[4].expon=2;
terms[5].coeff=1;
terms[5].expon=0;
add(0,1,2,5,&startD,&finishD);
display(0,1);
display(2,5);
display(startD,finishD);
}
Lab Component:
1. Design, Develop and Implement a menu driven Program in C for the following Array
Operations
a. Creating an Array of N Integer Elements
b. Display of Array Elements with Suitable Headings
c. Exit.
Support the program with functions for each of the above operations.
#include<stdio.h>
void create_array(int *arr,int n)
{
printf("Enter %d array elements one by one\n",n);
int i;
for(i=0;i<n;i++)
{
scanf("%d",&arr[i]);
}
}
void main()
{
int choice,n,sum,min,max;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
int *arr;
while(1)
{
printf("***********Array Menu Operations*******\n");
printf("1. Create\n");
printf("2. Display\n");
printf("3. Exit\n");
printf("Enter your choice\n");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("Create an array\n");
printf("Enter the value of n\n");
scanf("%d",&n);
arr=malloc(sizeof(int)*n);
create_array(arr,n);
break;
case 2:printf("Display the array\n");
display_array(arr,n);
break;
case 3:exit(0);
default:printf("Enter 1 2 or 3\n");
}
}
}
2. Design, Develop and Implement a menu driven Program in C for the following Array
operations
a. Inserting an Element (ELEM) at a given valid Position (POS)
b. Deleting an Element at a given valid Position POS)
c. Display of Array Elements
d. Exit. Support the program with functions for each of the above operations.
Program:
#include<stdio.h>
void create_array(int *arr,int N)
{
}
void display_array(int *arr, int N)
{
int i;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
for(i=0;i<N;i++)
printf("%d\n",arr[i]);
}
void delete_array(int *arr, int N, int POS)
{
int i;
for(i=POS;i<N-1;i++)
{
arr[i]=arr[i+1];
}
}
void main()
{
int N=0,choice,sum,min,ELEM,POS;
int *arr;
while(1)
{
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
printf("*****************Menu****************\n");
printf("1: Create\n");
printf("2: Display\n");
printf("3: Sum\n");
printf("4: Minimum\n");
printf("5: Insert\n");
printf("6: Delete\n");
printf("7: Exit\n");
printf("Enter your choice\n");
scanf("%d",&choice);
switch(choice)
{
case 1:printf("Enter the value of N\n");
scanf("%d",&N);
arr=(int*)malloc(sizeof(int)*N);
create_array(arr,N);
break;
case 2:if(N>0)
display_array(arr,N);
else
printf("Nothing to display\n");
break;
case 3:sum=sum_array(arr,N);
printf("Sum of the array=%d\n",sum);
break;
case 4: min=min_array(arr,N);
printf("Sum of the array=%d\n",min);
break;
case 5: printf("Enter the ELEMENT \n");
scanf("%d",&ELEM);
printf("Enter the POSITION\n");
scanf("%d",&POS);
N=N+1;
arr=realloc(arr,N*sizeof(int));
insert_array(arr,N,ELEM,POS);
break;
case 6:printf("Enter the POSITION\n");
scanf("%d",&POS);
delete_array(arr,N,POS);
N=N-1;
arr=realloc(arr,N*sizeof(int));
break;
case 7:exit(0);
default:printf("Invalid choice \n");
break;
}
}
}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Module-2
Stacks
Stacks are a special kind of data structure in which insertion and deletion happens at the same end
called top of the stack. Stack follows a Last-In-First-Out data structure. Books arranged on top of
each other, plates arranged in a reception, box of pringles potato chips and many others are real time
examples of the stack.
Stack Operations:
1. CREATE – used to create an empty stack of specific size.
2. PUSH – used to insert an element to the top of the stack
3. POP – used to remove an element from the top of the stack.
4. DISPLAY – display all the elements of the stack.
Stack States:
Stack can enter a state called “Overflow” when one tries to push an element to the stack beyond
its capacity. Stack can also enter a state called “Underflow” when one tries to pop an element from
an empty stack.
Stacks are static, if the size is fixed during compile time and once stack reaches this size, more
elements cannot be pushed. The memory for such a stack is allocated in the stack area of the memory.
Stacks can also be dynamic. Memory for such a stacks is allocated in the heap area of the memory.
Once size of the stack reaches max size, memory is doubled and reallocated.
{
printf("Stack overflow\n");
return;
}
arr[++top].data=ele;
}
void main()
{
stack arr[MAXSIZE];
push(arr,10);
push(arr,20);
push(arr,30);
display(arr);
push(arr,40);
push(arr,50);
push(arr,60);
push(arr,70);
display(arr);
pop(arr);
pop(arr);
pop(arr);
pop(arr);
pop(arr);
pop(arr);
}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
int isEmpty()
{
if(top==-1)
return 1;
return 0;
}
void push(stack *arr,int ele)
{
isFull(arr);
arr[++top].ele=ele;
}
void pop(stack *arr)
{
if(isEmpty())
{
printf("Stack Underflow..\n");
return;
}
printf("Popped Element=%d\n",arr[top].ele);
top--;
}
void display(stack *arr)
{
int i;
if(isEmpty(arr))
{
printf("Stack Empty..\n");
return;
}
for(i=top;i>=0;i--)
{
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
printf("%d\n",arr[i].ele);
}
}
void main()
{
stack *arr;
arr=malloc(sizeof(stack)*MAXSIZE);
push(arr,10);
push(arr,20);
push(arr,30);
push(arr,40);
push(arr,50);
push(arr,60);
push(arr,70);
push(arr,50);
push(arr,60);
push(arr,70);
pop(arr);
pop(arr);
display(arr);
}
System Stack:
- A special stack used by programs to process function calls.
- Each function is allotted an area called “Activation Record” or “Stack frame”
- Only one function can execute at any time. Hence function to be selected is one at the top of
stack
- PUSH- whenever a function is called, new stack frame is pushed on top of stack
- POP – whenever a function execution is completed, stack frame from top is popped
Queue:
Queue is a data structure that follows First In First Out Order (FIFO). Elements are inserted at “rear
end” and elements are deleted from “front end”. Such a queue is also called Single Ended Queue.
There are many applications of queue like:
(i) People waiting in queue for ticket booking
(ii) People waiting in queue to get vaccine
(iii) People waiting in queue for lunch during reception
(iv) Students waiting in a queue to collect library books
There are 2 types of Queue: Static Queue (fixed size) and Dynamic Queue (flexible size).
In Static Queue, max size of the queue (number of elements) is fixed during compilation. When the
size limit reaches, “Queue Overflow” state occurs. Similarly, when queue is empty, no element can
be deleted. If an attempt to deletion is done, it leads to a state called “Queue Underflow”. Further
memory for static queue is allocated in stack.
#define MAXSIZE 5
typedef struct
{
int data;
}queue;
int rear=-1,front=-1; //Pointers used in Single Ended Queue
int isFull(queue arr[MAXSIZE])
{
if(rear==MAXSIZE-1)
{
return 1; //Queue is full
}
return 0; //Queue is not full
}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
}
void display(queue arr[MAXSIZE])
{
int i;
if(isEmpty(arr))
{
printf("Queue empty\n");
return;
}
for(i=front+1;i<=rear;i++)
{
printf("%d\n",arr[i].data);
}
}
void main()
{
queue arr[MAXSIZE];
addq(arr,20);
addq(arr,30);
addq(arr,50);
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
addq(arr,60);
addq(arr,120);
addq(arr,130);
display(arr);
deleteq(arr);
deleteq(arr);
deleteq(arr);
}
void display(queue arr[MAXSIZE])
{
int i,j;
j=front+1;
for(i=0;i<cnt;i++)
{
printf("%d\n",arr[j].data);
j=(j+1)%MAXSIZE;
}
}
void main()
{
queue arr[MAXSIZE];
addq(arr,20);
addq(arr,30);
addq(arr,40);
display(arr);
addq(arr,50);
addq(arr,60);
addq(arr,70);
display(arr);
deleteq(arr);
deleteq(arr);
// display(arr);
addq(arr,100);
addq(arr,110);
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
addq(arr,120);
display(arr);
}
printf("Element deleted=%d\n",arr[front].data);
cnt--;
}
void display(queue *arr)
{
int i,j;
j=front+1;
for(i=0;i<cnt;i++)
{
printf("%d\n",arr[j].data);
j=(j+1)%MAXSIZE;
}
}
void main()
{
//queue arr[MAXSIZE];
queue *arr=malloc(sizeof(queue)*MAXSIZE);
addq(arr,20);
addq(arr,30);
addq(arr,40);
display(arr);
addq(arr,50);
addq(arr,60);
addq(arr,70);
display(arr);
deleteq(arr);
deleteq(arr);
// display(arr);
addq(arr,100);
addq(arr,110);
addq(arr,120);
display(arr);
}
Browser history is a memory maintained by each browser. Whenever user browses a page, it is
added to the history. Pages can be added to both ends and also removed from either end. Hence
double ended queue is used for browser history management.
Variations of Dequeue:
There are two variations of dequeue: (i) Input Restricted dequeue (Input-Rear end no insertion only,
deletion, but at front end both insertion and deletion can be done)
(ii) Output Restricted dequeue: (Output- front end no deletion, only insertion. However insertion and
deletion can be done at rear end)
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Priority Queues:
A Priority Queue is a collection of elements with each element assigned a priority. Deletion
of an element is based on following rules:
1. An element of higher priority before lower priority
2. For same priority elements, FIFO
Timesharing systems with high priority programs first and programs with normal priority into
standard queue
In Linear List, it is a collection of nodes connected with link. Each node contains INFO
(Information/data), PRN (Priority Number) and Link (pointer to the next node). For last node, pointer
is null.
❑ Rule: Lower numbers indicate higher priority
❑ Higher priority nodes are behind lower priority
❑ Same priority nodes are arranged in the order added
Insertion:
For insertion search for a node whose priority is greater than this node
Deletion:
Deletion is always done by removing first node
Eg:
(AAA,1), (BBB,1), (CCC,4), (DDD,3), (EEE,2)
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Hence with linear list, elements need to be shuffled each time, a new element of higher priority is to
be added. Instead of shuffling elements again and again, another solution is to use multiple queues.
A separate queue is maintained for each priority level. Separate front and rear pointers are maintained
for each such queue. The front and rear pointers are captured in separate arrays. Arrays for front and
rear, contains position of front and rear for each queue represented by the priority level. Further, these
arrays are used to construct a matrix . Rows of the matrix represents priority level and columns contain
the elements of the queue.
Eg:
Here, consider row 1, front is 2 and rear is 2. Hence element currently is AAA. In case new element
is to be added to row 1(Queue with priority 1), it will be added at position 3. Similarly for row 2, new
element will be added at position 4 (rear is 3) and element will be deleted from position 1 (front is 1).
x=a/b-c+d*e-a*c
=4/2-2+3*3-4*2
=2-2+3*3-4*2
=2-2+9-4*2
=2-2+9-8
=2+7-8
=9-8
=1
If number of operands is 1, operator is unary. Likewise, if operands is 2, operator is binary and for 3
operands, operator is ternary.
Types of Expressions:
There are 3 types of expressions based on the position of operator. If operator is inbetween operands,
expression is called “Infix Expression”. If operator comes before operands, expression is “Prefix”
and if operator comes after operands, expression is “Postfix”. Prefix expressions are also called
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
“Polish” and postfix expressions are also called “Reverse Polish or suffix”. Postfix and Prefix
expressions are used by compilers due to efficiency concerns during evaluation.
Eg:
𝒂∗𝒃∗𝒄
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
−𝒂 + 𝒃 − 𝒄 + 𝒅
𝒂 ∗ −𝒃 + 𝒄
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
(𝒂 + 𝒃) ∗ 𝒅 + 𝒆/(𝒇 + 𝒂 ∗ 𝒅) +c
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
GOTO STEP 1
STEP 4: IF CURRENT TOKEN IS EOS, PRINT TOS and EXIT
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
}
int pop(stack arr[MAX])
{
return arr[top--].data;
}
void main()
{
char expr[MAX];
stack arr[MAX];
int num1,num2,i;
printf("Enter the valid postfix expression\n");
scanf("%s",expr);
for(i=0;i<strlen(expr);i++)
{
if(isdigit(expr[i])) //digit
{
push(arr,expr[i]-'0');
}
else
{
num2=pop(arr);
num1=pop(arr);
switch(expr[i])
{
case '+':push(arr,num1+num2);
break;
case '-':push(arr,num1-num2);
break;
case '*':push(arr,num1*num2);
break;
case '/':push(arr,num1/num2);
break;
}
}
}
printf("Ans=%d\n",arr[top].data);
}
Recursion:
Recursion is the process of function calling itself. Recursive functions are written using recurrence
relations. Recursion is ended by specifying base criteria. A stack frame is created for each call during
recursive function.
{
if(n==1) return 1;
else
return n*fact(n-1);
}
void main()
{
int n=5;
printf("%d\n",fact(n));
}
Recurrence relation:
𝒏 = 𝟎 𝒐𝒓 𝒏 = 𝟏 𝒏
𝒇𝒊𝒃(𝒏) = {
𝒏>𝟏 𝒇𝒊𝒃(𝒏 − 𝟏) + 𝒇𝒊𝒃(𝒏 − 𝟐)
C Program:
int gcd(int m, int n)
{
if(n!=0)
return gcd(n,m%n);
else
return m;
}
void main()
{
int m=81,n=27;
int ans=gcd(m,n);
printf("%d\n",ans);
}
Tower of Hanoi:
It is a mathematical game or puzzle consisting of three legs and a number of disks of
various diameters, which can slide onto any leg. The puzzle begins with the disks stacked on one leg
in order of decreasing size, the smallest at the top, thus approximating a conical shape. The objective
of the puzzle is to move the entire stack to the last leg, obeying the following rules:
1. Only one disk may be moved at a time.
2. Each move consists of taking the upper disk from one of the stacks and placing it on
top of another stack or on an empty leg.
3. No disk may be placed on top of a disk that is smaller than it.
Recursive Solution:
1. MOVE TOP N-1 DISKS FROM LEG A to LEG B
2. MOVE THE TOP DISK FROM LEG A TO LEG C
3. MOVE TOP N-1 DISKS FROM LEG B TO LEG C
C program:
void toh(int N,char A,char B, char C)
{
if(N>0) //termination condition (base condition)
{
toh(N-1,A, C, B);
printf("%c->%c\n",A,C);
toh(N-1,B,A,C);
}
}
void main()
{
int N=3;
toh(N,'A','B','C');
}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Lab Component:
Design, Develop and Implement a menu driven Program in C for the following operations on
STACK of Integers (Array Implementation of Stack with maximum size MAX)
a. Push an Element on to Stack
b. Pop an Element from Stack
c. Demonstrate Overflow and Underflow situations on Stack
d. Display the status of Stack
e. Exit
Support the program with appropriate functions for each of the above operations
#define MAX 5
typedef struct
{
int data;
}stack;
int top=-1;
int isFull(stack arr[MAX])
{
if(top==MAX-1)
return 1; //Full
return 0; //Not full
}
int i;
for(i=top;i>=0;i--)
{
printf("%d\n",arr[i].data);
}
}
void main()
{
stack arr[MAX];
int choice, ele;
while(1)
{
printf("****Stack Operations*****\n");
printf("1. PUSH\n");
printf("2. POP\n");
printf("3. DISPLAY\n");
printf("4. EXIT\n");
printf("Enter your choice\n");
scanf("%d",&choice);
switch(choice)
{
case 1:printf("Enter the element\n");
scanf("%d",&ele);
push(arr,ele);
break;
case 2:pop(arr);
break;
case 3:display(arr);
break;
case 4: exit(0);
default:printf("Enter 1/2/3/4\n");
}
}
}
Design, Develop and Implement a Program in C for the following Stack Application:
a. Evaluation of Suffix expression with single digit operands and operators: +, -, *, /, %, ^
#define MAX 20
typedef struct
{
int data;
}stack;
int top=-1;
void push(stack arr[MAX],int ele)
{
arr[++top].data=ele;
}
int pop(stack arr[MAX])
{
return arr[top--].data;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
}
void main()
{
char expr[MAX];
stack arr[MAX];
int num1,num2,i;
printf("Enter the valid postfix expression\n");
scanf("%s",expr);
for(i=0;i<strlen(expr);i++)
{
if(isdigit(expr[i])) //digit
{
push(arr,expr[i]-'0');
}
else
{
num2=pop(arr);
num1=pop(arr);
switch(expr[i])
{
case '+':push(arr,num1+num2);
break;
case '-':push(arr,num1-num2);
break;
case '*':push(arr,num1*num2);
break;
case '/':push(arr,num1/num2);
break;
}
}
}
printf("Ans=%d\n",arr[top].data);
}
Design, Develop and Implement a Program in C for the following Stack Application:
b. Solving Tower of Hanoi problem with n disks
Module-3
Linked Lists:
A linked list or one way list is a linear collection of nodes. Each node contains data and a
pointer next that points to the next element in the list. Addition, deletion, updation, traversal,
searching, sorting, merging frequently needed on the linked list.
Each node consists of information and a pointer called NEXT. NEXT points to the next element in
the list. If the node is the last node, NEXT is a null pointer. (NULL). The beginning node is referred
by a special pointer called START.
Example:
Linked list can be used to store patient list admitted to beds. The linked list is sorted in the ascending
order of patient names alphabetically.
Representation of Linked List in the memory:
Eg-1: Represent the word SCAM in memory:
Two arrays are maintained: INFO and LINK. String is scanned from left to right. For each character,
place is allotted in the INFO array wherever free. The next location of each letter is recorded in the
corresponding position in the LINK array.
Discuss how an employee file containing 3 records with fields (EMPID, Name, Designation,
Rank) can be stored using linked lists and without linked lists. Compare and contrast both
approaches
An employee file with 3 records and 4 fields can be stored as 3 X 4 2D array. Each row will represent
an employee record and each column represent field of employee. This organization will help to
access any employee data directly with appropriate row and column indexing. However, when
number of employees increase, the contiguous allocation issue arises and fails. Further adding and
removing an element in the specific positions would incur lot of penalty with the amount of shifting
involved. Hence a linked list representation would solve issues of memory, complexity of addition
and deletion operations. For linked list representation, each node represents and employee with
information field divided into 4 separate fields for empid, name, designation and rank and a next field
to point to the next employee record.
*/
void traverse(node *start)
{
node*temp=start;
while(temp!=NULL)
{
printf("%d->",temp->data);
temp=temp->next;
}
printf("\b\b \n");
}
/** Function to count the number of nodes of a singly linked list (SLL)
Algorithm:
Step 1: Initialize temp node with START and COUNT to 0.
Step 2: If temp==NULL, goto Step 6
Step 3: COUNT=COUNT+1
Step 4: Move to next node with temp=temp->next
Step 5: Goto Step 2
Step 6: Print COUNT and EXIT
*/
/** Function to search an element KEY in the unsorted singly linked list (SLL)
Algorithm:
Step 1: Initialize temp node with START
Step 2: If temp==NULL, goto Step 6
Step 3: If temp->data == KEY, PRINT SUCCESSFUL SEARCH and EXIT
Step 4: Move to next node with temp=temp->next
Step 5: Goto Step 2
Step 6: PRINT UNSUCCESSFULL SEARCH and EXIT
*/
temp=temp->next;
}
printf("Unsuccessful search\n");
/** Function to search an element KEY in the sorted singly linked list (SLL)
Algorithm:
Step 1: Initialize temp node with START
Step 2: If temp==NULL, goto Step 7
Step 3: If temp->data == KEY, PRINT SUCCESSFUL SEARCH and EXIT
Step 4: If temp->data > KEY, PRINT UNSUCCESSFUL SEARCH and EXIT
Step 5: Move to next node with temp=temp->next
Step 6: Goto Step 2
Step 8: PRINT UNSUCCESSFULL SEARCH and EXIT
*/
temp=temp->next;
}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
printf("Unsuccessful search\n");
}
void main()
{
node *n1,*n2,*n3,*n4,*n5;
n1=malloc(sizeof(node)); //Dynamic memory allocation to create any node
n2=malloc(sizeof(node));
n3=malloc(sizeof(node));
n4=malloc(sizeof(node));
n5=malloc(sizeof(node));
n1->data=9;
n2->data=10;
n3->data=15;
n4->data=20;
n5->data=51;
n1->next=n2;
n2->next=n3;
n3->next=n4;
n4->next=n5;
n5->next=NULL;
traverse(n1);
count_nodes(n1);
// search_unsorted_list(n1);
search_sorted_list(n1);
}
#include<stdlib.h>
typedef struct
{
int data;
struct node *next;
}node;
node *start=NULL;
}
/**Function to insert a given node after a given location
Algorithm:
STEP 1: Get the data for new node
STEP 2; Get the required location LOC
STEP 3: Allocate memory for new node
STEP 4: Assign data to the new node
STEP 5: Set temp to START and CNT=1
STEP 6: IF temp==NULL goto STEP 10
STEP 7: IF CNT==LOC, Goto STEP 9
STEP 8: Move temp to next node: temp=temp->next and CNT=CNT+1. Goto STEP 6
STEP 9: Set: newnode->next to temp->next and temp->next to newnode.
STEP 10: EXIT
*/
void insert_after()
{
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
int ele,loc,cnt=1;
node *newnode,*temp;
printf("Enter the element\n");
scanf("%d",&ele);
printf("Enter the location\n");
scanf("%d",&loc);
newnode=malloc(sizeof(node));
newnode->data=ele;
temp=start;
while(temp!=NULL)
{
if(cnt==loc)
{
break;
}
else
{
temp=temp->next;
cnt++;
}
}
newnode->next=temp->next;
temp->next=newnode;
void insert_sorted_list()
{
int ele;
node *newnode;
node *prev,*temp;
printf("Enter the element\n");
scanf("%d",&ele);
newnode=malloc(sizeof(node));
newnode->data=ele;
prev=start;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
temp=start;
while(temp!=NULL)
{
if(temp->data>ele)
{
break;
}
else
{
prev=temp;
temp=temp->next;
}
}
prev->next=newnode;
newnode->next=temp;
void traverse()
{
node *temp=start;
while(temp!=NULL)
{
printf("%d->",temp->data);
temp=temp->next;
}
}
void main()
{
insert_begining();
insert_begining();
traverse();
insert_after();
traverse();
insert_sorted_list();
traverse();
#include<stdio.h>
#include<stdlib.h>
typedef struct
{
int data;
struct node *next;
}node;
node *start=NULL;
void insert_node(int ele)
{
node* newnode;
newnode=malloc(sizeof(node));
newnode->data=ele;
newnode->next=start;
start=newnode;
}
/**
Algorithm to delete a node after given location
Step 1: Initialize count to 1
Step 2: Initialize temp to start and declare cur as node pointer.
Step 3: If temp is not NULL
3.1.: Check count is same as user given node location (loc)
3.2: If same Goto Step 4
3.3: Move temp to temp->next
3.4: Increment count
3.5: Goto Step 3
Step 4: Assign cur as temp->next
Step 5: Assign temp->next to cur->next
Step 6: Free cur node
Step 7: Exit
**/
}
void display()
{
node*temp=start;
while(temp!=NULL)
{
printf("%d->",temp->data);
temp=temp->next;
}
}
void main()
{
insert_node(20);
insert_node(30);
insert_node(21);
display();
delete_node_after(1);
display();
int data;
struct node *next;
}node;
node *start=NULL;
void insert_node(int ele)
{
node* newnode;
newnode=malloc(sizeof(node));
newnode->data=ele;
newnode->next=start;
start=newnode;
}
/**
Algorithm to delete a node with matching item
Step 1: Initialize temp and prev node pointers to start.
Step 2: If temp is not NULL
2.1.: Check temp->data and item
2.2: If same Goto Step 3
2.3: Assign prev as temp
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
if(temp->data==item)
break;
prev=temp;
temp=temp->next;
}
prev->next=temp->next;
free(temp);
}
void display()
{
node*temp=start;
while(temp!=NULL)
{
printf("%d->",temp->data);
temp=temp->next;
}
}
void main()
{
insert_node(20);
insert_node(30);
insert_node(21);
display();
delete_match(30);
display();
}
int data;
struct node *next;
}node;
node *start=NULL;
void insert_node(int ele)
{
node* newnode;
newnode=malloc(sizeof(node));
newnode->data=ele;
newnode->next=start;
start=newnode;
}
void sort_list()
{
int temp;
node*t=start,*s;
while(t!=NULL)
{
s=t->next;
while(s!=NULL)
{
if(s->data<t->data)
{
temp=s->data;
s->data=t->data;
t->data=temp;
}
s=s->next;
}
t=t->next;
}
}
void main()
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
{
insert_node(20);
insert_node(30);
insert_node(21);
display();
sort_list();
display();
Algorithm-SIMPLE MERGE
STEP 1: REFER LIST1 BY A POINTER TEMP1
STEP 2: REFER LIST2 BY A POINTER TEMP2
STEP 3: IF TEMP1!=NULL
3.1 ADD TEMP1 to END OF MERGEDLIST
3.2 MOVE TEMP1=TEMP1->NEXT
3.3 GOTO STEP3
STEP 4: IF TEMP2!=NULL
4.1 ADD TEMP2 to END OF MERGEDLIST
4.2 MOVE TEMP2=TEMP2->NEXT
4.3 GOTO STEP4
STEP 5 EXIT
Corresponding C program:
#include<stdlib.h>
typedef struct
{
int data;
struct node *next;
}node;
node *start1=NULL,*start2=NULL,*start3=NULL;
node* insert_front(node*s,int ele)
{
node* newnode;
newnode=malloc(sizeof(node));
newnode->data=ele;
newnode->next=s;
s=newnode;
return s;
}
void display(node *s)
{
node*temp=s;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
while(temp!=NULL)
{
printf("%d->",temp->data);
temp=temp->next;
}
printf("\b\b ");
}
node* concat(node*start1, node*start2,
node *start3)
{
node* temp=start1,*temp3;
node *newnode;
//Append list1 to outputlist
while(temp!=NULL)
{
newnode=malloc(sizeof(node));
newnode->data=temp->data;
newnode->next=NULL;
if(start3==NULL)
start3=newnode;
else
{
temp3=start3;
while(temp3->next!=NULL)
temp3=temp3->next;
temp3->next=newnode;
}
temp=temp->next;
}
//Appending List 2 to output list
temp=start2;
while(temp!=NULL)
{
newnode=malloc(sizeof(node));
newnode->data=temp->data;
newnode->next=NULL;
if(start3==NULL)
start3=newnode;
else
{
temp3=start3;
while(temp3->next!=NULL)
temp3=temp3->next;
temp3->next=newnode;
}
temp=temp->next;
}
return start3;
}
void main()
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
{
start1=insert_front(start1,22);
start1=insert_front(start1,19);
start1=insert_front(start1,15);
display(start1);
printf("\n");
start2=insert_front(start2,23);
start2=insert_front(start2,17);
display(start2);
printf("\n");
start3=concat(start1,start2,start3);
display(start3);
}
Algorithm-SORTED MERGE
STEP 1: REFER LIST1 BY A POINTER TEMP1
STEP 2: REFER LIST2 BY A POINTER TEMP2
STEP 3: IF TEMP1!=NULL AND TEMP2!=NULL
3.1: IF TEMP1->DATA<TEMP2->DATA
3.1.1: ADD TEMP1 to MERGEDLIST,
TEMP1=TEMP1->NEXT, GOTO STEP 3
3.1.2: ELSE ADD TEMP2 to MERGEDLIST.
TEMP2=TEMP2->NEXT, GOTO STEP 3
STEP 4: IF TEMP1!=NULL, COPY RESIDUAL NODES TO MERGEDLIST and EXIT
STEP 5 IF TEMP2!=NULL, COPY RESIDUAL NODES TO MERGEDLIST and EXIT
Corresponding C program:
#include<stdlib.h>
typedef struct
{
int data;
struct node *next;
}node;
node* start1=NULL,*start2=NULL,*start3=NULL;
node* insert_front(int ele,node*start)
{
node* newnode;
newnode=malloc(sizeof(node));
newnode->data=ele;
newnode->next=start;
start=newnode;
return start;
}
{
printf("%d->",temp->data);
temp=temp->next;
}
}
void sorted_merge()
{
node*temp1=start1;
node* temp2=start2;
node* temp3=start3;
while(temp1!=NULL && temp2!=NULL)
{
if(temp1->data < temp2->data)
{
insert_end(temp1->data);
temp1=temp1->next;
}
else
{
insert_end(temp2->data);
temp2=temp2->next;
}
}
while(temp1!=NULL) //copy residual nodes of list1
{
insert_end(temp1->data);
temp1=temp1->next;
}
while(temp2!=NULL) //copy residual nodes of list2
{
insert_end(temp2->data);
temp2=temp2->next;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
}
}
void main()
{
start1=insert_front(22,start1);
start1=insert_front(11,start1);
start1=insert_front(10,start1);
display(start1);
printf("\n");
start2=insert_front(16,start2);
start2=insert_front(9,start2);
display(start2);
printf("\n");
sorted_merge();
display(start3);
Circular linked lists have a number of advantages over traditional linked lists.
• As there is no defined beginning or end to the list, data can be added and removed from the
list at any time. This makes circular linked lists ideal for applications where data needs to be
constantly added or removed, such as in a real-time application.
• Since data is stored in a ring-like structure, it can be accessed in a continuous loop. This makes
circular linked lists ideal for applications where data needs to be processed in a continuous
loop, such as in a real-time application or simulation.
• As there is no defined beginning or end to the list, circular linked lists are typically more
efficient than traditional linked lists when it comes to memory usage. This is because
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
traditional linked lists often require additional memory for pointers that point to the beginning
and end of the list. Circular linked lists, on the other hand, only require a single pointer to be
stored in memory – the head pointer.
• Circular linked lists are often easier to implement than traditional linked lists. This is because
traditional linked lists often require the use of additional data structures, such as stacks and
queues, to keep track of the list's beginning and end. Circular linked lists, on the other hand,
only require a singly linked list data structure.
node *start=NULL;
}
}
newnode->data=ele;
if(start==NULL)
{
start=newnode;
start->next=start;
return;
}
while(temp->next!=start)
{
temp=temp->next;
}
temp->next=newnode;
newnode->next=start;
}
}
newnode->next=temp->next;
temp->next=newnode;
}
{
node*prev=start,*temp=start;
while(temp->next!=start)
{
prev=temp;
temp=temp->next;
}
prev-> next=start;
free(temp);
// delete_end();
// delete_front();
delete_specific_pos(2);
display();
}
It is advantageous over other data structures because it allows for quick insertion and deletion of
elements. Additionally, it is easy to implement and can be used in a variety of applications.
node*start=NULL;
newnode->next=start;
start->prev=newnode;
start=newnode;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
}
}
}
}
while(temp->next!=NULL)
{
if(cnt==pos)
break;
cnt++;
temp=temp->next;
}
ntemp=temp->next;
newnode->next=ntemp;
temp->next=newnode;
newnode->prev=ntemp;
ntemp->prev=newnode;
void delete_front()
{
node *temp=start;
start=start->next;
start->prev=NULL;
free(temp);
}
//Displaying a DLL
void display()
{
node *temp=start;
while(temp!=NULL)
{
printf("%d->",temp->data);
temp=temp->next;
}
}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
//Reversing a DLL
void reverse_list()
{
node *temp=start;
while(temp->next!=NULL)
temp=temp->next;
while(temp!=NULL)
{
printf("%d<-",temp->data);
temp=temp->prev;
}
}
The header node does not represent an item in the linked list. This data part of this node is generally
used to hold any global information about the entire linked list. The next part of the header node
points to the first node in the list.
#include<stdlib.h>
typedef struct
{
int data;
struct node*next;
}node;
node *head;
{
printf("%d->",temp->data);
temp=temp->next;
}
}
Lab Component:
Develop a C program to create Singly Linked List (SLL) of Integer Data (Linked Stack)
a. Create a SLL stack of N integer.
b. Display of SLL
c. Linear search.
#include<stdlib.h>
typedef struct
{
int data;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
push(30);
push(23);
push(12);
display();
linear_search(22);
pop();
display();
} node;
node*start1=NULL,*start2=NULL,*start3=NULL;
void main()
{
start1=insert_end(start1,20);
start1=insert_end(start1,30);
start1=insert_end(start1,10);
display(start1);
start2=insert_end(start2,15);
start2=insert_end(start2,11);
display(start2);
start3=concat(start1,start2,start3);
display(start3);
Design, Develop and Implement a menu driven Program in C for the following operations on
Doubly Linked List (DLL) of Professor Data with the fields: ID, Name, Branch, Area of
specialization.
a. Create a DLL stack of N Professor’s Data.
#include<stdlib.h>
typedef struct
{
int id;
char name[30];
char branch[30];
char area[30];
struct node *next;
struct node *prev;
}node;
node* top=NULL;
void push(int id, char*name, char*branch,char *area)
{
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
node*newnode;
newnode=malloc(sizeof(node));
newnode->id=id;
strcpy(newnode->name,name);
strcpy(newnode->branch,branch);
strcpy(newnode->area,area);
newnode->next=NULL;
newnode->prev=NULL;
if(top==NULL) //Nothing
{
top=newnode;
}
else
{
top->prev=newnode;
newnode->next=top;
top=newnode;
}
}
void pop()
{
node*temp;
if(top==NULL)
{
printf("Stack underflow\n");
return;
}
temp=top;
top=top->next;
if(top!=NULL)
top->prev=NULL;
printf("Popped Professor ID=%d\n",temp->id);
free(temp);
}
void display()
{
node*temp=top;
while(temp!=NULL)
{
printf("%d,%s,%s,%s->",temp->id,temp->name,
temp->branch,temp->area);
temp=temp->next;
}
}
void main()
{
int choice,id;
char name[30],branch[30],area[30];
while(1)
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
{
printf("******DLL Stack ************\n");
printf("1. PUSH\n");
printf("2. POP\n");
printf("3. DISPLAY\n");
printf("4. EXIT\n");
printf("Enter the choice\n");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("Enter ID,Name,Branch,Area\n");
scanf("%d%s%s%s",&id,name,branch,area);
push(id,name,branch,area);
break;
case 2:pop();
break;
case 3: display();
break;
case 4:exit(0);
default: printf("Enter 1/2/3/4\n");
}
}
}
b. Create a DLL queue of N Professor’s Data Display the status of DLL and count the
number of nodes in it.
#include<stdlib.h>
typedef struct
{
int id;
char name[30];
char branch[30];
char area[30];
struct node *next;
struct node *prev;
}node;
node* rear=NULL,*front=NULL;
void addq(int id, char*name, char*branch,char *area)
{
node*newnode;
newnode=malloc(sizeof(node));
newnode->id=id;
strcpy(newnode->name,name);
strcpy(newnode->branch,branch);
strcpy(newnode->area,area);
newnode->next=NULL;
newnode->prev=NULL;
if(rear==NULL) //Nothing
{
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
front=newnode;
rear=newnode;
}
else //Something
{
rear->next=newnode;
newnode->prev=rear;
rear=newnode;
}
}
void deleteq()
{
node*temp;
if(front==NULL)
{
printf("Queue underflow\n");
return;
}
temp=front;
front=front->next;
if(front!=NULL)
front->prev=NULL;
printf("Popped Professor ID=%d\n",temp->id);
free(temp);
}
void display()
{
node*temp=front;
while(temp!=NULL)
{
printf("%d,%s,%s,%s->",temp->id,temp->name,
temp->branch,temp->area);
temp=temp->next;
}
}
int count_nodes()
{
int cnt=0;
node *temp=front;
while(temp!=NULL)
{
cnt++;
temp=temp->next;
}
return cnt;
}
void main()
{
int choice,id,cnt;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
char name[30],branch[30],area[30];
while(1)
{
printf("******DLL Queue ************\n");
printf("1. ADD Queue\n");
printf("2. Delete Queue\n");
printf("3. DISPLAY\n");
printf("4. COUNT\n");
printf("5. EXIT\n");
printf("Enter the choice\n");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("Enter ID,Name,Branch,Area\n");
scanf("%d%s%s%s",&id,name,branch,area);
addq(id,name,branch,area);
break;
case 2:deleteq();
break;
case 3: display();
break;
case 4:cnt=count_nodes();
printf("Number of nodes=%d\n",cnt);
break;
case 5:exit(0);
default: printf("Enter 1/2/3/4\n");
}
}
}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Module-4
Trees
Overview of a Tree:
A tree is a nonlinear hierarchical data structure that consists of nodes connected by edges. Other data
structures such as arrays, linked list, stack, and queue are linear data structures that store data
sequentially. In order to perform any operation in a linear data structure, the time complexity increases
with the increase in the data size. This behaviour is not acceptable in today's computational world.
Different tree data structures allow quicker and easier access to the data as it is a non-linear data
structure.
Eg: A Tree with 8 nodes having 4 levels. Different nodes connected with parent-child relationship.
These trees grow top down and special node at the top is called root.
(ii) Every company/institution has an organization chart that shows the flow of authority in
the organization. Such an organization chart is depicted below:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
(iv) The website for any firm/organization/industry will have various webpages
organized as a tree fashion shown next:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
(v) Most trending network of the present era is the social network which is modelled as
a tree with subscribers as nodes and their relationship as edges.
Descendant Tree is a tree in which children of each node are its descendants. Hence path from root
to any node gives the list of descendants. One such descendant tree is as follows. In this example,
descendants of Osco-Umbrian are: Osco and Umbrian.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Ancestor Tree
Descendant Tree
Definition of a tree:
A tree is a finite set of one or more nodes such that:
(1) Specially designated node called root
(2) Remaining nodes are partitioned into n disjoint sets, each of which are subtrees
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Tree Terminologies:
Consider an example tree for stating various terminologies:
Node of a tree: Any item which as information and branch to other node. In case of leaf node,
branch is NULL. Eg: in Node C, information is C and branch is to D.
Degree of a node: The number of subtrees of any node is its degree. Eg. B has degree 2 as it has 2
subtrees. If the degree of any node is 0, it is called Leaf Node. If degree of a node is non-zero, it is
called Non-terminal node.
Siblings: Children of the same parent are called siblings. E and F are siblings as they are children of
the same parent B.
Ancestors: Ancestors of any node is the list of nodes in the path from root to that node.
Level: Level of a tree starts with 1 at root node. Subsequently number increases with other
descendants.
Representation of Trees:
There are 3 ways of representing trees:
(i) List Representation
(ii) Leftchild, right sibling representation
(iii) Binary Tree (degree two) representation
:
Linked list representation proceeds as follows:
:
Left-child Right sibling representation proceeds as follows:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
In the binary tree representation, each node can contain max two children. To get such a
representation, tree is first converted to left-child, right sibling representation. Using such a
representation, each right sibling is converted to right subtree.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
:
Binary Tree representation proceeds as follows:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Binary Trees:
A binary tree is a finite set of nodes that is either empty or consists of root node and two disjoint
binary trees called left subtree and right subtree. Each node of a binary tree consists of three items:
• data item
• address of left child
• address of right child
The complete binary tree is similar to the full binary tree except for the two differences which are
given below:
o The filling of the leaf node must start from the leftmost side.
o It is not mandatory that the last leaf node must have the right sibling.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
3. Skewed Trees:
A binary tree can be called a skewed binary tree if all nodes have one child or no child at all. They
can be of two types:
• Left Skewed Binary Tree
• Right Skewed Binary Tree
Left Skewed Binary Tree
If all nodes are having a left child or no child at all then it can be called a left skewed binary tree. In
this tree all children at right side remain null.
typedef struct
{
int data;
struct node *leftChild;
struct node *rightChild;
}node;
Hence for all nodes in the tree, nodes in the linked list is created. Later left and right child connectivity
through pointers are drawn.
(i) Inorder:
In the Inorder traversal, node comes in between left and right child. Hence technique is to go to
dead left and start printing nodes in LNR fashion for each subtree. The C recursive procedure for
inorder traversal is:
(ii) Preorder:
In the preorder traversal, node is printed in the path it is traversed towards left and right subtrees.
Hence technique is NLR (Node Left Right). The C recursive procedure for preorder traversal is:
void preorder(treePointer ptr)
{
if(ptr)
{
printf(“%d”,ptr->data);
preorder(ptr->leftChild);
preorder(ptr->rightChild);
}
}
Level-order traversal:
In the level order traversal of a tree, the nodes are visited level by level starting from level-1. In
each level, nodes are visited left to right. C procedure for level-order traversal is:
void levelorder(treePointer ptr)
{
treePointer queue[MAX_SIZE];
if(!ptr) return;
addq(ptr);
for(;;)
{
ptr=deleteq();
if(ptr)
{
printf(“%d”,ptr->data);
if(ptr->leftChild)
addq(ptr->leftChild);
if(ptr->rightChild)
addq(ptr->rightChild);
}
else
break;
}
}
The stack processing along with inorder calls is shown in the following:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Algorithm:
Step 1: In Preorder, leftmost is the root
Step 2: Find position of root in Inorder
Step 3: Leftmost elements form left subtree and rightmost elements form right subtree.
Step 4: Recursively perform Step 2 and 3 until all nodes are traverses
Problems:
1
Step 1: Root: leftmost element in the preorder =>
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Step 2: Check for position of root in Inorder. Leftsubtree of 1=>[4,2,7,5] Rightsubtree of 1=>[8,6,3]
Step 3: In left subtree, 2 appears before all elements in preorder. Hence 2 is the child of 1
Step 3: Now check for position of 2 in inorder. Leftsubtree of 2=[4] and Rightsubtree of 2=[7,5]
Step 4: Since 4 is the only node in LST of 2, make it as left child
4 5
2 3
4 5
7
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Step 7: In LST of 3, 6 appears first in preorder and its position is left of 3. Similarly position of 8 is
to the left of 6 as shown in Inorder.
1
3
2
6
4 5
8
7
Algorithm:
Step 1: In Postorder, rightmost is the root
Step 2: Find position of root in Inorder
Step 3: Leftmost elements form left subtree and rightmost elements form right subtree.
Step 4: Recursively perform Step 2 and 3 until all nodes are traverses
Step 2: Check for position of root in Inorder. Leftsubtree of 1=>[4,2,7,5] Rightsubtree of 1=>[8,6,3]
Step 3: In left subtree, 2 appears after all elements in postorder. Hence 2 is the child of 1
Step 3: Now check for position of 2 in inorder. Leftsubtree of 2=[4] and Rightsubtree of 2=[7,5]
Step 4: Since 4 is the only node in LST of 2, make it as left child
4
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
4 5
2 3
4 5
Step 7: In LST of 3, 6 appears last in postorder and its position is left of 3. Similarly position of 8 is
to the left of 6 as shown in Inorder.
1
3
2
6
4 5
8
7
trees with threads are known as threaded binary trees. Each node in a threaded binary tree either
contains a link to its child node or thread to other nodes in the tree.
In one-way threaded binary trees, a thread will appear either in the right or left link field of a node. If
it appears in the right link field of a node then it will point to the next node that will appear on
performing in order traversal. Such trees are called Right threaded binary trees. If thread appears
in the left field of a node, then it will point to the nodes inorder predecessor. Such trees are called Left
threaded binary trees. Left threaded binary trees are used less often as they don't yield the last
advantages of right threaded binary trees. In one-way threaded binary trees, the right link field of last
node and left link field of first node contains a NULL. In order to distinguish threads from normal
links they are represented by dotted lines.
The above figure shows the inorder traversal of this binary tree yields D, B, E, A, C, F. When this
tree is represented as a right threaded binary tree, the right link field of leaf node D which contains a
NULL value is replaced with a thread that points to node B which is the inorder successor of a node
D. In the same way other nodes containing values in the right link field will contain NULL value.
In two-way threaded Binary trees, the right link field of a node containing NULL values is replaced
by a thread that points to nodes inorder successor and left field of a node containing NULL values is
replaced by a thread that points to nodes inorder predecessor.
The above figure shows the inorder traversal of this binary tree yields D, B, E, G, A, C, F. If we
consider the two-way threaded Binary tree, the node E whose left field contains NULL is replaced by
a thread pointing to its inorder predecessor i.e. node B. Similarly, for node G whose right and left
linked fields contain NULL values are replaced by threads such that right link field points to its
inorder successor and left link field points to its inorder predecessor. In the same way, other nodes
containing NULL values in their link fields are filled with threads.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
In the above figure of two-way threaded Binary tree, we noticed that no left thread is possible for the
first node and no right thread is possible for the last node. This is because they don't have any inorder
predecessor and successor respectively. This is indicated by threads pointing nowhere. So in order to
maintain the uniformity of threads, we maintain a special node called the header node. The header
node does not contain any data part and its left link field points to the root node and its right link field
points to itself. If this header node is included in the two-way threaded Binary tree then this node
becomes the inorder predecessor of the first node and inorder successor of the last node. Now threads
of left link fields of the first node and right link fields of the last node will point to the header node.
typedef struct
{
char data;
struct node *leftChild;
struct node* rightChild;
int leftThread;
int rightThread;
}node;
C code:
node* insucc(node* ptr)
{
node* temp1;
temp1=ptr->leftChild;
if(!ptr->rightThread)
while(!temp1->leftThread)
temp1=temp1->leftChild;
return temp1;
}
if(temp==ptr)break;
printf(“%c”,temp->data);
}
}
In the above figure, we can observe that the root node is 40, and all the nodes of the left subtree are
smaller than the root node, and all the nodes of the right subtree are greater than the root node.
Similarly, we can see the left child of root node is greater than its left child and smaller than its right
child. So, it also satisfies the property of binary search tree. Therefore, we can say that the tree in the
above image is a binary search tree.
Suppose if we change the value of node 35 to 55 in the above tree, check whether the tree will be
binary search tree or not.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
In the above tree, the value of root node is 40, which is greater than its left child 30 but smaller than
right child of 30, i.e., 55. So, the above tree does not satisfy the property of Binary search tree.
Therefore, the above tree is not a binary search tree.
• Otherwise, if the element is larger than the root node, then insert it as the root of the right
subtree.
--problems—
--problems—
Deletion in BST
Case (i) Node to be deleted is a leaf node
Set its parent right/left child to NULL
Delete (free) the NODE
Eg: Deleting node 85 in tree shown left
12,25,30,50,52,60,70,75,85
Expression Trees:
❑ The expression tree is a tree used to represent the various expressions.
❑ The tree data structure is used to represent the expressional statements.
❑ In this tree, the internal node always denotes the operators. The leaf nodes always denote the
operands.
Evaluation of the tree:
❖ Evaluate left subtree
❖ Evaluate right subtree
❖ Evaluate root
Eg: Evaluate the tree:
1.
Solution:
+ + 34
7 * 7 27
3
9
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
2.
Solution:
+
+
* /
* /
5 7
- 21 5 7
5 21
10 5
+
+ 28
* 3
25 3
5
5
Lab Component:
Given an array of elements, construct a complete binary tree from this array in level order
fashion. That is, elements from left in the array will be filled in the tree level wise starting from
level 0. Ex: Input : arr[] = {1, 2, 3, 4, 5, 6}
#include<stdlib.h>
typedef struct
{
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
int data;
struct node *leftChild;
struct node *rightChild;
}node;
node* create_node(int data)
{
node* newnode;
newnode=malloc(sizeof(node));
newnode->data=data;
newnode->leftChild=NULL;
newnode->rightChild=NULL;
return newnode;
}
void main()
{
int a[]={1,2,3,4,5,6,7};
int n=sizeof(a)/sizeof(a[0]),i,cnt;
node* arr[n+1];
for(i=1;i<=n;i++)
arr[i]=create_node(a[i-1]);
i=1;
cnt=1;
while(cnt<n)
{
arr[i]->leftChild=arr[2*i];
cnt++;
if(cnt>=n)
{
printf("%d->(%d)\n",arr[i]->data,
arr[2*i]->data);
break;
}
arr[i]->rightChild=arr[2*i+1];
printf("%d->(%d,%d)\n",arr[i]->data,
arr[2*i]->data,arr[2*i+1]->data);
i++;
cnt++;
}
Design, Develop and Implement a menu driven Program in C for the following operations on
Binary Search Tree (BST) of Integers a. Create a BST of N Integers b. Traverse the BST in
Inorder, Preorder and Post Order
#include<stdlib.h>
typedef struct
{
int data;
struct node *leftChild;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
printf("%d,",ptr->data);
preorder(ptr->leftChild);
preorder(ptr->rightChild);
}
}
postorder(ptr->leftChild);
postorder(ptr->rightChild);
printf("%d,",ptr->data);
}
}
Module-5
Graphs and Hashing
Need of Balanced Trees:
Consider a BST for the months of a year if input sequence is: JAN, FEB, MAR, APR, MAY, JUN,
JUL, AUG, SEP, OCT, NOV, DEC ( in the order of occurrence of the months).
Computation:
Month No. of comparisons JUL 4
AUG 4
JAN 1
FEB 2 SEP 4
MAR 2
OCT 5
APR 3
MAY 3 NOV 6
JUN 3
DEC 5
Hence AVG=42/12=3.5
Max=6 for NOV
Now, Enter the nodes in the sequence: JULY, FEB, MAY, AUG, DEC,MAR,OCT,APR,JAN,JUNE,
SEP,NOV
Resultant BST is:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
It can be observed that average number of comparisons and max comparisons are reduced due to
balancing of the BST. Balanced trees make searching faster and reduce the number of comparisons
required.
Now, Enter the months in the lexicographic order and resultant BST is:
Thus degenerate trees have worst case performance as they are completely imbalanced.
Observations:
- Average and maximum search time is reduced if binary tree is maintained as complete
binary trees
- However, such trees are difficult to grow dynamically
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
- These balanced trees have satisfactory search, insertion and deletion time properties
AVL Trees
AVL Tree is invented by GM Adelson - Velsky and EM Landis in 1962. The tree is named AVL in
honour of its inventors. AVL Tree can be defined as height balanced binary search tree in which each
node is associated with a balance factor which is calculated by subtracting the height of its right sub-
tree from that of its left sub-tree.
Tree is said to be balanced if balance factor of each node is in between -1 to 1, otherwise, the
tree will be unbalanced and need to be balanced.
AVL Rotations
To balance itself, an AVL tree may perform the following four kinds of rotations:
• Left rotation
• Right rotation
• Left-Right rotation
• Right-Left rotation
Left Rotation:
Left rotation is performed to solve imbalance caused due to skewing of the tree on the right
side. Eg:
Right Rotation:
Right rotation is performed to solve imbalance caused due to skewing of the tree on the left
side. Eg:
Left-Right rotation
2 rotations i.e first Left and then right is performed on a subtree which is imbalanced due to first
growth of left child and subsequently right child of this left child. Eg:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Right-Left rotation
2 rotations i.e first Right and then Left is performed on a subtree which is imbalanced due to first
growth of right child and subsequently leftt child of this left child. Eg:
Insert MAY
Insert NOV
Insert APR
Insert AUG
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Insert JAN
Insert DEC
Insert JUL
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Insert FEB
RED-BLACK Trees
The red-Black tree is a binary search tree. The prerequisite of the red-black tree is that we should
know about the binary search tree. Each node in the Red-black tree contains an extra bit that represents
a color to ensure that the tree is balanced during any operations performed on the tree like insertion,
deletion, etc.
In this tree, Searching performance of worst case will be same as linear search. Hence need of
balanced trees arises. AVL is a balanced tree strict height, whereas Red-Black performs balancing
with colors.
Observations of Red-Black Trees:
❑ Red-Black tree is used because the AVL tree requires many rotations when the tree is large,
whereas the Red-Black tree requires a maximum of two rotations to balance the tree.
❑ The main difference between the AVL tree and the Red-Black tree is that the AVL tree is
strictly balanced, while the Red-Black tree is not completely height-balanced.
❑ Insertion is easier in the AVL tree as the AVL tree is strictly balanced, whereas deletion and
searching are easier in the Red-Black tree as the Red-Black tree requires fewer rotations
Properties of Red-Black Trees:
❖ Self balancing through rotation and recoloring
❖ Each node stores 1 extra bit for color
❖ Root node always black color
❖ NIL vs Internal nodes – different
❖ Node – Red, children should be black
❖ Never! Red-Red parent-child relationship exists
❖ Every path from a node to any of its descendant's NIL node should have same number of
black nodes.
Procedure for construction of Red-Black Tree:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Insert 10
Insert 18
Insert 7
Insert 15
Insert 16
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Insert 30
Insert 25
Eg:
Eg:
Eg:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Splay Trees:
A splay tree is a self-balancing tree. AVL and Red-Black trees are also self-balancing trees then.
It has one extra property that makes it unique is splaying. A splay tree contains the same
operations as a Binary search tree, i.e., Insertion, deletion and searching, but it also contains one
more operation, i.e., splaying. So. all the operations in the splay tree are followed by splaying.
Splay trees are not strictly balanced trees, but they are roughly balanced trees. Let's understand
the search operation in the splay-tree.
Rotations
There are six types of rotations used for splaying:
1. Zig rotation (Right rotation)
2. Zag rotation (Left rotation)
3. Zig zag (Zig followed by zag)
4. Zag zig (Zag followed by zig)
5. Zig zig (two right rotations)
6. Zag zag (two left rotations)
Eg: Searching 7 in the given BST. Since parent on left, rotate right (Zig Rotation)
Insert 10
Insert 17
Insert 7
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Top-down splaying
In top-down splaying, we first perform the splaying on which the deletion is to be performed and then
delete the node from the tree. Once the element is deleted, we will perform the join operation.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
B-Trees:
B Tree is a specialized m-way tree that can be widely used for disk access. A B-Tree of order m can
have at most m-1 keys and m children. One of the main reason of using B tree is its capability to store
large number of keys in a single node and large key values by keeping the height of the tree relatively
small.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
A B tree of order m contains all the properties of an M way tree. In addition, it contains the following
properties.
❑ Root node has atleast 2 children
❑ All nodes other than root node have atleast ⌈𝒎/𝟐⌉ children
❑ All external nodes are at the same level.
It is not necessary that, all the nodes contain the same number of children but, each node must
have m/2 number of nodes.
When m=3, degree is (2,3) => 2-3 tree
When
Eg. of 2-3 m=4,
B-Tree degree is (2,4)=> 2-3-4 tree
Insert 10:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Insert 20
Insert 70
Insert 80
Insert 30
Insert 60
Here, a node can have a maximum of Here, a node can have maximum two
1. 'M'(where 'M' is the order of the tree) child child nodes (they are also known as sub-
nodes. trees).
The nodes are present in 'inorder' traversal It can be sorted in inorder, preorder or
3. mode. postorder traversal.
It has a height of logM N (where 'M' is the It has a height of log2 N (base 2, log N,
4. order of tree and N is the number of nodes). where N is the number of nodes).
Operations are performed on a B-Tree when Binary tree operations are used when data
5. data is loaded to the disk. is loaded to the RAM (quicker).
It can also be used to insert the data or key It is also used in code optimization
7. in a B-tree. methods.
Graphs
A graph G, consists of 2 sets V- vertices and E-edges. G=(V,E). In the Undirected graph, pair
representing edge is unordered and in the directed graph, it is ordered. Eg:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
In graph theory, Self edges and multi-graphs are not allowed. Eg:
Definitions:
Maximum number of edges in a graph = n(n-1)/2
For an undirected graph of n vertices,
Each vertex can be maximum connected to (n-1) vertices
Hence number of edges for each vertex=(n-1)
Total Number of edges=(n-1)+(n-1)+..+(n-1)
=n(n-1)
But same edge is counted twice for an undirected graph
Hence total number of edges=n(n-1)/2
If (u,v) is an edge in G, then we say vertices u and v are adjacent and (u,v) is incident on vertices u
and v
Eg: For the graph shown below, for edge (1,3) 1 and 3 are adjacent and (1,3) is incident on vertices
1 and 3.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
A subgraph of G is a graph G’ such that V(G’) is a subset of V(G) and E(G’) is a subset of E(G)
Eg: for graph G shown below,
can be a subgraph obtained by deleting vertex 2 and all edges incident on vertex
2.
A path from vertex u to v is a set of vertices u,i1,i2..v such that (u,i1), (i1,i2)… (in,v) are edges. Length
of path=no of edges in it
In an undirected graph G, two vertices u and v are connected iff there is a path from u to. An
undirected graph G is connected, iff for every distinct pair of vertices there exists a path.
Eg:
Degree of a vertex is number of edges incident to that vertex. For a directed graph, in-degree of a
vertex is the number of incoming edges. For a directed graph, out-degree of a vertex is the number of
outgoing edges.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Graph Representations:
Adjacency Matrix:
n graph theory, an adjacency matrix is a dense way of describing the finite graph structure. It is the
2D matrix that is used to map the association between the graph nodes.
If a graph has n number of vertices, then the adjacency matrix of that graph is n x n, and each entry
of the matrix represents the number of edges from one vertex to another.
An adjacency matrix is also called as connection matrix. Sometimes it is also called a Vertex
matrix.
If an Undirected Graph G consists of n vertices then the adjacency matrix of a graph is n x n matrix
A = [aij] and defined by -
aij = 1 {if there is an edge from Vi to Vj}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
aij = 0 {Otherwise}
Eg: Graph and its adjacency matrix
Hence it the adjacency matrix for undirected graph, edge from (1,2) creates an entry 1 for (1,2) and
(2,1) in the matrix and symmetry is preserved. However, for a directed graph, no symmetry is
considered while constructing the adjacency matrix.
For an undirected graph, degree of any vertex is its row sum. For a digraph, row-sum is outdegree
and column-sum is indegree. Drawback of Adjacency matrix is wastage of memory. If only few edges
are present in the graph, then most of entries becomes 0 and leads to a sparse matrix. Thus this
representation becomes memory inefficient.
What will be the adjacency matrix for the below directed weighted graph?
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Solution:
In the above figure, we can see that there is a linked list or adjacency list for every node of the graph.
From vertex A, there are paths to vertex B and vertex D. These nodes are linked to nodes A in the
given adjacency list.
An adjacency list is maintained for each node present in the graph, which stores the node value and
a pointer to the next adjacent node to the respective node. If all the adjacent nodes are traversed, then
store the NULL in the pointer field of the last node of the list.
The sum of the lengths of adjacency lists is equal to twice the number of edges present in an
undirected graph.
Now, consider the directed graph, and let's see the adjacency list representation of that graph.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
For a directed graph, the sum of the lengths of adjacency lists is equal to the number of edges present
in the graph.
Now, consider the weighted directed graph, and let's see the adjacency list representation of that
graph.
In the case of a weighted directed graph, each node contains an extra field that is called the weight of
the node.
In an adjacency list, it is easy to add a vertex. Because of using the linked list, it also saves space.
Solution:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Solution:
Solution:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Adjacency List:
For an undirected graph, degree of any vertex is number of nodes in the chain of that vertex. For a
digraph, out-degree is the number of nodes in the chain of that vertex. For a digraph, in-degree is the
number of nodes in the chain of that vertex in Inverse Adjacency list.
and a set of linked list of edge information (Edge List). There is one entry in the node directory for
each node of the graph. The directory entry for node i points to a linked adjacency list for node i. each
record of the linked list area appears on two adjacency lists: one for the node at each end of the
represented edge.
Format of edge list:
m V1 V2 L1 L2
where,
m- Boolean field used to mark visited nodes during BFS or DFS
V1 and V2- source and destination vertices of the edge under consideration
L1- Link to next edge of V1
L2- Link to next edge of V2
Eg:
Consider the graph
Suppose we consider node 0 as a root node. Therefore, the traversing would be started from node 0.
Once node 0 is removed from the Queue, it gets printed and marked as a visited node.
Once node 0 gets removed from the Queue, then the adjacent nodes of node 0 would be inserted in a
Queue as shown below:
Now the node 1 will be removed from the Queue; it gets printed and marked as a visited node
Once node 1 gets removed from the Queue, then all the adjacent nodes of a node 1 will be added in a
Queue. The adjacent nodes of node 1 are 0, 3, 2, 6, and 5. But we have to insert only unvisited nodes
in a Queue. Since nodes 3, 2, 6, and 5 are unvisited; therefore, these nodes will be added in a Queue
as shown below:
The next node is 3 in a Queue. So, node 3 will be removed from the Queue, it gets printed and marked
as visited as shown below:
Once node 3 gets removed from the Queue, then all the adjacent nodes of node 3 except the visited
nodes will be added in a Queue. The adjacent nodes of node 3 are 0, 1, 2, and 4. Since nodes 0, 1 are
already visited, and node 2 is present in a Queue; therefore, we need to insert only node 4 in a Queue.
Now, the next node in the Queue is 2. So, 2 would be deleted from the Queue. It gets printed and
marked as visited as shown below:
Once node 2 gets removed from the Queue, then all the adjacent nodes of node 2 except the visited
nodes will be added in a Queue. The adjacent nodes of node 2 are 1, 3, 5, 6, and 4. Since the nodes 1
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
and 3 have already been visited, and 4, 5, 6 are already added in the Queue; therefore, we do not need
to insert any node in the Queue.
The next element is 5. So, 5 would be deleted from the Queue. It gets printed and marked as visited
as shown below:
Once node 5 gets removed from the Queue, then all the adjacent nodes of node 5 except the visited
nodes will be added in the Queue. The adjacent nodes of node 5 are 1 and 2. Since both the nodes
have already been visited; therefore, there is no vertex to be inserted in a Queue.
The next node is 6. So, 6 would be deleted from the Queue. It gets printed and marked as visited as
shown below:
Once the node 6 gets removed from the Queue, then all the adjacent nodes of node 6 except the visited
nodes will be added in the Queue. The adjacent nodes of node 6 are 1 and 4. Since the node 1 has
already been visited and node 4 is already added in the Queue; therefore, there is not vertex to be
inserted in the Queue.
The next element in the Queue is 4. So, 4 would be deleted from the Queue. It gets printed and marked
as visited. Once the node 4 gets removed from the Queue, then all the adjacent nodes of node 4 except
the visited nodes will be added in the Queue. The adjacent nodes of node 4 are 3, 2, and 6. Since all
the adjacent nodes have already been visited; so, there is no vertex to be inserted in the Queue.
DFS:
In DFS traversal, the stack data structure is used, which works on the LIFO (Last In First Out)
principle. In DFS, traversing can be started from any node, or we can say that any node can be
considered as a root node until the root node is not mentioned in the problem. In the case of BFS, the
element which is deleted from the Queue, the adjacent nodes of the deleted node are added to the
Queue. In contrast, in DFS, the element which is removed from the stack, then only one adjacent node
of a deleted node is added in the stack.
Consider the graph:
The node 0 has two adjacent nodes, i.e., 1 and 3. Now we can take only one adjacent node, either 1
or 3, for traversing. Suppose we consider node 1; therefore, 1 is inserted in a stack and gets printed
as shown below:
Now we will look at the adjacent vertices of node 1. The unvisited adjacent vertices of node 1 are 3,
2, 5 and 6. We can consider any of these four vertices. Suppose we take node 3 and insert it in the
stack as shown below:
Consider the unvisited adjacent vertices of node 3. The unvisited adjacent vertices of node 3 are 2
and 4. We can take either of the vertices, i.e., 2 or 4. Suppose we take vertex 2 and insert it in the
stack as shown below:
The unvisited adjacent vertices of node 2 are 5 and 4. We can choose either of the vertices, i.e., 5 or
4. Suppose we take vertex 4 and insert in the stack as shown below:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Now we will consider the unvisited adjacent vertices of node 4. The unvisited adjacent vertex of node
4 is node 6. Therefore, element 6 is inserted into the stack as shown below:
After inserting element 6 in the stack, we will look at the unvisited adjacent vertices of node 6. As
there is no unvisited adjacent vertices of node 6, so we cannot move beyond node 6. In this case, we
will perform backtracking. The topmost element, i.e., 6 would be popped out from the stack as
shown below:
The topmost element in the stack is 4. Since there are no unvisited adjacent vertices left of node 4;
therefore, node 4 is popped out from the stack as shown below:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
The next topmost element in the stack is 2. Now, we will look at the unvisited adjacent vertices of
node 2. Since only one unvisited node, i.e., 5 is left, so node 5 would be pushed into the stack above
2 and gets printed as shown below:
Now we will check the adjacent vertices of node 5, which are still unvisited. Since there is no vertex
left to be visited, so we pop the element 5 from the stack as shown below:
We cannot move further 5, so we need to perform backtracking. In backtracking, the topmost element
would be popped out from the stack. The topmost element is 5 that would be popped out from the
stack, and we move back to node 2 as shown below:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Now we will check the unvisited adjacent vertices of node 2. As there is no adjacent vertex left to be
visited, so we perform backtracking. In backtracking, the topmost element, i.e., 2 would be popped
out from the stack, and we move back to the node 3 as shown below:
Now we will check the unvisited adjacent vertices of node 3. As there is no adjacent vertex left to be
visited, so we perform backtracking. In backtracking, the topmost element, i.e., 3 would be popped
out from the stack and we move back to node 1 as shown below:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
After popping out element 3, we will check the unvisited adjacent vertices of node 1. Since there is
no vertex left to be visited; therefore, the backtracking will be performed. In backtracking, the
topmost element, i.e., 1 would be popped out from the stack, and we move back to node 0 as shown
below:
We will check the adjacent vertices of node 0, which are still unvisited. As there is no adjacent vertex
left to be visited, so we perform backtracking. In this, only one element, i.e., 0 left in the stack, would
be popped out from the stack as shown below:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
As we can observe in the above figure that the stack is empty. So, we have to stop the DFS traversal
here, and the elements which are printed is the result of the DFS traversal.
Full form BFS stands for Breadth First DFS stands for Depth First Search.
Search.
Data Structure Queue data structure is used for Stack data structure is used for the BFS
the BFS traversal. traversal.
Backtracking BFS does not use the backtracking DFS uses backtracking to traverse all the
concept. unvisited nodes.
Number of BFS finds the shortest path having In DFS, a greater number of edges are
edges a minimum number of edges to required to traverse from the source vertex to
traverse from the source to the the destination vertex.
destination vertex.
Optimality BFS traversal is optimal for those DFS traversal is optimal for those graphs in
vertices which are to be searched which solutions are away from the source
closer to the source vertex. vertex.
Suitability for It is not suitable for the decision It is suitable for the decision tree. Based on
decision tree tree because it requires exploring the decision, it explores all the paths. When
all the neighboring nodes first. the goal is found, it stops its traversal.
Hashing
Hashing is a popular technique for quickly storing and retrieving data. The primary reason for using
hashing is that it produces optimal results by performing optimal searches. If we try to search, insert,
or delete any element in a balanced binary search tree, the time complexity for the same is O. (logn).
Now, there may be times when our applications need to perform the same operations in a faster, more
optimised manner, and this is where hashing comes into play. All of the above operations in hashing
can be completed in O(1), or constant time. It is critical to understand that hashing's worst-case time
complexity remains O(n), but its average time complexity is O. (1).
Static Hashing:
In Static hashing, dictionary pairs (key,value) are stored in a table called hash-table. Hash table is
static and changes very infrequently. Hash table should be created with larger size to accommodate
all possible insertions in then future. Hash table is Partitioned to buckets. Each bucket can have one
or more slots. Each slot is big enough to accommodate one dictionary pair.
Key density
Key density of a hash table = n/T
n – number of pairs
T- total possible number of keys
Compute key density for keys which are atmost 6 digits long and there are 1000 dictionary pairs
T= total number of possible keys= 9*10^5=900000
n=1000
Hence, key density=1000/900000=1/900=0.00111111111
Hence fraction of the usage of keys is very small.
Construct a hash table for C library functions, with first letter of the function goes to the
appropriate bucket. Assume 2 slots for each bucket
Solution:
❑ Hash table with 26 buckets and 2 slots is not useful due to large number of collisions
Desirable properties of hash functions:
❑ Easy to compute
❑ Minimizes the number of collisions
❑ Collisions are unavoidable, hence mechanisms to handle collisions is desired.
❑ Hash function maps a key to a bucket
Example:
Suppose the size of the Hash Table (m) = 10 (0 - 9) maximum digits required for the index is 1
Element (x) = 12 ⇒ x2 = 144
Mid 1 digit of 144 is 4, so the element x=12 will be stored at the index=4 in the hash table with the
size of 10 slots.
Another Example:
Suppose the size of the Hash Table (m) = 1000 (0 - 999) maximum digits required for the index is 3
Element (x) = 87431 ⇒ x2 = 7644179761
The possible 3 digit mids of 7644179761 are 417 or 179, we can pick any of those mids. If we pick
419 then the element x=87431 will be stored at the index=419 in the hash table with the size of
1000 slots.
There are very less chances of collision in this method.
Further examples:
Folding Method
In this method, the keys are divided into parts which are then combined (or “folded”) together
and often transformed into the address – Two types of folding are used, shift folding and boundary
folding
In shift folding, the parts are placed underneath each other and then processed (for
example, by adding) – Using a Social Security number, say 123-45-6789, we can divide
it into three parts - 123, 456, and 789 – and add them to get 1368 – This can then be
divided modulo hash_table size to get the address.
With boundary folding, the key is visualized as being written on a piece of paper and
folded on the boundaries between the parts. The result is that alternating parts of the key
are reversed, so the Social Security number part would be 123, 654, 789, totalling 1566 –
As can be seen, in both versions, the key is divided into even length parts of some fixed
size, plus any leftover digits – Then these are added together and the result is divided
modulo the table size – Consequently this is very fast and efficient, especially if bit strings
are used instead of numbers
Further examples:
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Digit Analysis:
}
return number;
}
Code for adding ascii value of each character with left shifting every alternate character by 8
bits:
unsigned int stringToIntA(char *key)
{
int number=0;
while(*key)
{
number+=*key++;
if(*key) number+=(*key++)<<8;
}
return number;
}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
Linear Probing
Linear probing is one of the forms of open addressing. As we know that each cell in the hash table
contains a key-value pair, so when the collision occurs by mapping a new key to the cell already
occupied by another key, then linear probing technique searches for the closest free locations and
adds a new key to that empty cell. In this case, searching is performed sequentially, starting from the
position where the collision occurs till the empty cell is not found.
Quadratic Probing
In case of linear probing, searching is performed linearly. In contrast, quadratic probing is an open
addressing technique that uses quadratic polynomial for searching until a empty slot is found.
It can also be defined as that it allows the insertion ki at first free location from (u+i2)%m where i=0
to m-1.
Let's understand the quadratic probing through an example.
Consider the same example which we discussed in the linear probing.
A = 3, 2, 9, 6, 11, 13, 7, 12 where m = 10, and h(k) = 2k+3
The key values 3, 2, 9, 6 are stored at the indexes 9, 7, 1, 5, respectively. We do not need to apply the
quadratic probing technique on these key values as there is no occurrence of the collision.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
The index value of 11 is 5, but this location is already occupied by the 6. So, we apply the quadratic
probing technique.
When i = 0
Index= (5+02)%10 = 5
When i=1
Index = (5+12)%10 = 6
Since location 6 is empty, so the value 11 will be added at the index 6.
Random probing
• Random probing avoids clustering by making the probe sequence depend on the key
• With random probing, the probe sequence is generated by the output of a pseudorandom
number generator seeded by the key (possibly together with another seed component that is
the same for every key, but is different for different tables)
• The insert algorithm for random hashing is then:
1. Create RNG seeded with K. Set indx = RNG.next() mod M.
2. If table location indx already contains the key, no need to insert it. Done!
3. Else if table location indx is empty, insert key there. Done!
4. Else collision. Set indx = RNG.next() mod M.
5. If all M locations have been probed, give up. Else, go to 2.
• Random probing is easy to analyze, but because of the "expense" of random number
generation, it is not often used; double hashing works about as well
Double Hashing
Double hashing is an open addressing technique which is used to avoid the collisions. When the
collision occurs then this technique uses the secondary hash of the key. It uses one hash value as an
index to move forward until the empty location is found.
In double hashing, two hash functions are used. Suppose h1(k) is one of the hash functions used to
calculate the locations whereas h2(k) is another hash function. It can be defined as "insert ki at first
free place from (u+v*i)%m where i=(0 to m-1)". In this case, u is the location computed using the
hash function and v is equal to (h2(k)%m).
Eg:
Dynamic Hashing:
Dynamic hashing is used to overcome the problems of static hashing like bucket overflow.
Data buckets grow or shrink as the records increases or decreases. This method is also known
as Extendable hashing method. This method makes hashing dynamic, i.e., it allows insertion
or deletion without resulting in poor performance.
How to search a key
❑ Calculate the hash address of the key.
❑ Check how many bits are used in the directory, and these bits are called as i.
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
❑ Take the least significant i bits of the hash address. This gives an index of the directory.
❑ Now using the index, go to the directory and find bucket address where the record might be.
Eg:
Lab Component
Design, Develop and implement a program in C for the following operations on Graph (G) of
cities a. Create a Graph of N cities using Adjacency Matrix
#include<stdio.h>
void create_adjacent_matrix(int N,int cities[N][N])
{
int i,j,edges,src,dest;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
cities[i][j]=0;
}
}
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
}
void print_adjacent_matrix(int N,int cities[N][N])
{
int i,j;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
printf("%3d",cities[i][j]);
}
printf("\n");
}
void main()
{
int cities[6][6];
create_adjacent_matrix(6,cities);
print_adjacent_matrix(6,cities);
Print all the nodes reachable from a given starting node in a diagraph using DFS/BFS method.
int edges,i,src,dest;
printf("Enter the number of edges\n");
scanf("%d",&edges);
for(i=0;i<edges;i++)
{
printf("Enter the vertices of the edge\n");
scanf("%d%d",&src,&dest);
grp[src][dest]=1;
}
}
void display_digraph(int N,int grp[N][N])
{
int i,j;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{
printf("%3d",grp[i][j]);
}
printf("\n");
}
}
void depth_first_search(int node,int N,int grp[N][N],
int visited[N])
{
int i;
visited[node]=1;
printf("Visited node=%d\n",node);
for(i=0;i<N;i++)
{
if(grp[node][i]==1 && visited[i]==0)
{
depth_first_search(i,N,grp,visited);
}
}
{
if(visited[i]==0 && grp[cnode][i]==1)
{
queue[rear++]=i;
visited[i]=1;
}
}
}
}
void main()
{
int N=7,i;
int grp[N][N],visited[N];
initialize_digraph(N,grp);
create_digraph(N,grp);
display_digraph(N,grp);
printf("Depth First Search....\n");
for(i=0;i<N;i++)
visited[i]=0;
depth_first_search(0,N,grp,visited);
printf("Breadth First Search....\n");
for(i=0;i<N;i++)
visited[i]=0;
breadth_first_search(0,N,grp,visited);
}
int N=7;
int hash_table[7];
void initialize_hash_table()
{
int i;
for(i=0;i<N;i++)
hash_table[i]=-1;
}
void insert(int key)
{
int index;
index=key%N;
while(hash_table[index]!=-1)
{
index=(index+1)%N;
}
hash_table[index]=key;
}
void print_hash_table()
{
int i;
DATA STRUCTURES AND APPLICATIONS DEPT. OF AIML
for(i=0;i<N;i++)
{
printf("%d\n",hash_table[i]);
}
}
void main()
{
initialize_hash_table();
insert(76);
insert(93);
insert(40);
insert(47);
insert(10);
insert(55);
print_hash_table();
}