Professional Documents
Culture Documents
LESSON NOTES
Vision
Mission
To keep pace with advancements in knowledge and make the students competitive and
capable at the global level.
To create an environment for the students to acquire the right physical, intellectual,
emotional and moral foundations and shine as torch bearers of tomorrow's society.
To strive to attain ever-higher benchmarks of educational excellence.
To develop highly talented individuals in Computer Science and Engineering to deal with
real world challenges in industry, education, research and society.
Mission of the Department
Motivate students to put their thoughts and ideas adoptable by industry or to pursue higher
studies leading to research
1. Empower students with a strong basis in the mathematical, scientific and engineering
fundamentals to solve computational problems and to prepare them for employment,
higher learning and R&D.
2. Gain technical knowledge, skills and awareness of current technologies of computer
science engineering and to develop an ability to design and provide novel engineering
solutions for software/hardware problems through entrepreneurial skills.
3. Exposure to emerging technologies and work in teams on interdisciplinary projects with
effective communication skills and leadership qualities.
4. Ability to function ethically and responsibly in a rapidly changing environment by applying
innovative ideas in the latest technology, to become effective professionals in Computer
Science to bear a life-long career in related areas.
1. Demonstrate understanding of the principles and working of the hardware and software
aspects of Embedded Systems.
Dept. of CSE, ATMECE Page 2
DS(18CS32)
2. Use professional Engineering practices, strategies and tactics for the development,
implementation and maintenance of software.
3. Provide effective and efficient real time solutions using acquired knowledge in various
domains.
Module – 3
Linked Lists: Definition, Representation of linked lists in Memory, Memory allocation; 10 Hours
Garbage Collection. Linked list operations: Traversing, Searching, Insertion, and
Deletion. Doubly Linked lists, Circular linked lists, and header linked lists. Linked
Stacks and Queues. Applications of Linked lists – Polynomials, Sparse matrix
representation. Programming Examples Textbook 1: Ch apter 4: 4.1 – 4.6, 4.8, Textbook
2: Ch apter 5: 5.1 – 5.10, RBT: L1, L2, L3
Module – 4
Trees: Terminology, Binary Trees, Properties of Binary trees, Array and linked 10 Hours
Representation of Binary Trees, Binary Tree Traversals - Inorder, postorder, preorder;
Additional Binary tree operations. Threaded binary trees, Binary Search Trees –
Definition, Insertion, Deletion, Traversal, Searching, Application of Trees-Evaluation of
Expression, Programming Examples
Textbook 1: Chapter 5: 5.1 –5.5, 5.7; Textbook 2: Chapter 7: 7.1 – 7.9 RBT: L1, L2, L3
Module – 5
Graphs: Definitions, Terminologies, Matrix and Adjacency List Representation Of 10 Hours
Graphs, Elementary Graph operations, Traversal methods: Breadth First Search and
Depth First Search. Sorting and Searching: Insertion Sort, Radix sort, Address
Calculation Sort. Hashing: Hash Table organizations, Hashing Functions, Static and
Dynamic Hashing. Files and Their Organization: Data Hierarchy, File Attributes, Text
Files and Binary Files, Basic File Operations, File Organizations and Indexing Textbook
1: Chapter 6 : 6.1 –6.2, Chapter 7:7.2, Chapter 8 : 8.1-8.3 Textbook 2: Chapter 8 : 8.1 –
8.7, Chapter 9 : 9.1-9.3, 9.7, 9.9 Reference 2: Chapter 16 : 16.1 - 16.7 RBT: L1, L2, L3
Course outcomes: The students should be able to:
Use different types of data structures, operations and algorithms
Apply searching and sorting operations on files
Use stack, Queue, Lists, Trees and Graphs in problem solving
Implement all data structures in a high-level language for problem solving.
Question paper pattern:
The question paper will have ten questions.
Each full Question consisting of 20 marks
There will be 2 full questions (with a maximum of four sub questions) from each module.
Each full question will have sub questions covering all the topics under a module.
The students will have to answer 5 full questions, selecting one full question from each
module
TextBooks:
1. Ellis Horowitz and Sartaj Sahni, Fundamentals of Data Structures in C, 2nd Ed, Universities Press,
2014.
2. Seymour Lipschutz, Data Structures Schaum's Outlines, Revised 1st Ed, McGraw Hill, 2014
Reference Books
MODULE 1
STRUCTURE
1.0 Introduction
1.1 Objective
1.2 Introduction to Data Structures
1.3 Basic types of Data Structures
1.4 Data Structure Operations
1.5 Data Structures in C
1.5.1 Defining a structure
1.5.2 Accessing Structure Members
1.5.3 Arrays of structures
1.5.4 Pointers to Structures
1.6 Type definitions and structures
1.7 Unions
1.8 Self Referential structure
1.9 Arrays in C
1.10 Multi Dimensional Arrays
1.11 Operations on Arrays in C
1.12 Sparse Matrices
1.13 Polynomials
1.14 Dynamically allocated arrays
1.5 Strings
1.16 Dynamic Memory Management Functions
1.0 Introduction
This module gives introduction to data structures and classification of data structures.
Structures and unions are explained in detail. Arrays and operation on arrays are highlighted.
Sparse matrix and polynomials are discussed.
1.1 Objective
Understand the concept of data structure operations, arrays, structures, unions.
#include<string.h>struc
t Books { char
title[50];
charauthor[50];
char subject[100];
intbook_id;
};
int main( ) {
/* book 1 specification */
=6495407;
/* book 2 specification */
Book2.book_id = 6495700;
return 0;
When the above code is compiled and executed, it produces the following result −
Book 1 subject : DS
You can pass a structure as a function argument in the same way as you pass any other variable or
pointer.
#include <stdio.h>
#include<string.h>str
title[50];
charauthor[50];
char subject[100];
intbook_id;
Dept. of CSE, ATMECE Page 11
DS(18CS32)
};
/* function declaration */
main( )
Book*/
/* book 1 specification */
=6495407;
/* book 2 specification */
Book2.book_id = 6495700;
printBook( Book1 );
printBook( Book2 );
return 0;
}
Void printBook( struct Books book ) {
Dept. of CSE, ATMECE Page 12
DS(18CS32)
When the above code is compiled and executed, it produces the following result −
Book subject : DS
We can also declare an array of structures in order to store records of n number of entities.
Below program demonstrates the sameconcept.
#include <stdio.h>
#include
<conio.h>structBo
oks{
char *title;
char *author;
char *subject;
intbook_id;
};
Dept. of CSE, ATMECE Page 13
DS(18CS32)
void main()
{
struct Books book[3];
int i;
for(i=0;i<2;i++)
{
scanf("%s%s%s%d",book[i].title,book[i].author,book[i].subject,&book[i].book_id);
}
for(i=0;i<2;i++)
{
printf("%s\t%s\t%s\t%d\n",book[i].title,book[i].author,book[i].subject,book[i].book_id);
}
getch();
}
1.5.4 Pointers to Structures
You can define pointers to structures in the same way as you define pointer to any other variable
Now, you can store the address of a structure variable in the above defined pointer variable. To
find the address of a structure variable, place the '&'; operator before the structure's name as
follows −
struct_pointer = &Book1;
To access the members of a structure using a pointer to that structure, you must use the →
operator as follows −
struct_pointer->title;
#include <stdio.h>
#include<string.h>s
title[50];
charauthor[50];
char subject[100];
intbook_id;
};
/* function declaration */
main( )
Book*/
/* book 1 specification */
=6495407;
/* book 2 specification */
Book2.book_id = 6495700;
printBook(&Book1 );
printBook(&Book2 );
return 0;
}
Void printBook( struct Books *book ) {
printf( "Book title : %s\n", book->title);
%s\n",book->subject);
}
When the above code is compiled and executed, it produces the following result
Book author
:Sahni Book
subject : DS
Shiney
6495700
{
int_ptrmyvar; // create a variable of the typeint_ptr
return 0;
}
It is also possible to use type definitions with structures. The name of the type definition
of a structure is usually in uppercase letters. Take a look at the example:
#include<stdio.
h>struct
telephone
{
char
*name;
int
number;
};
Typedefstruct telephone
TELEPHONEintmain()
{
TELEPHONEindex; // create a variable of the typeint_ptr
1.7 Unions
A union is like a structure in which all members are stored at the same address. Members of a
union can only be accessed one at a time. The union data type was invented to prevent memory
fragmentation. The union data type prevents fragmentation by creating a standard size for
certain data. Just like with structures, the members of unions can be accessed with the dot (.)
and arrow (->) operators. Take a look at this example:
#include<stdio.h>type
def union myunion
{
double
PI; int
B;
}MYUNION;
int main()
{
MYUNION
numbers;
numbers.PI = 3.14;
numbers.B = 50;
return 0;
}
If you would want to print the values of PI and B, only B value will be printed properly since
single memory is reserved to hold the data members’ value of union. Hence, 50 will be
displayed correctly.
Differences between structures and unions
Structure Union
Structure declaration starts with keyword Union declaration starts with keyword union
struct
Structure reserves memory for each data Union reserves memory i.e., equal to maximum
member separately data member size amongst all.
Any data member value can be accessed at Only one data member can be accessed at a
any time time
Ex: struct Book{ Ex: union Book{
intisbn; intisbn;
float price; float price;
char title[20]; char title[20];
}book; }book;
Total memory reserved will be Total memory reserved will be
sizeof(int)+sizeof(flaot)+(20*sizeof(char) Max(sizeof(int)+sizeof(flaot)+(20*sizeof(char))
struct struct_name
{
datatype datatypename;
struct_name *
pointer_name;
};
For example,
1.9 Arrays in C
In C programming, one of the frequently arising problems is to handle similar types of data. For
example, if the user wants to store marks of 100 students. This can be done by creating 100
variables individually but, this process is rather tedious and impracticable. This type of problem
can be handled in C programming using arrays.
An array is a sequence of data item of homogeneous value (same type).
Arrays are of two types: One-dimensional arrays, Multidimensional arrays
Declaration of one-dimensional array: data_typearray_name [array_size]; For
example: intage[5];
Here, the name of array is age. The size of array is 5, i.e., there are 5 items (elements) of
array age. All elements in an array are of the same type (int, in thiscase).
Array elements
Size of array defines the number of elements in an array. Each element of array can be accessed
and used by user according to the need of program.
For example: intage[5];
Figure 1.3
Note that, the first element is numbered 0 and so on. That means array indexing always starts
from 0 to n-1.
Here, the size of array is 5 times the size of int because there are 5 elements.
Suppose, the starting address of the array age[0] is 2120d and the size of int be 4 bytes. Then, the
next address (address of a[1]) will be 2124d, address of a[2] will be 2128d and so on.
It is not necessary to define the size of arrays during initialization. Below instruction justifies
it.int age[]={2,4,34,3,4};
In this case, the compiler determines the size of array by calculating the number of elements of
an array.
Figure 1.4
Accessing array elements
#include
<stdio.h>intmain(){
int marks[10],i,n,sum=0; printf("Enter
number of students: "); scanf("%d",&n);
for(i=0;i<n;++i){
printf("Enter marks of student%d: ",i+1);
scanf("%d",&marks[i]);
sum+=marks[i];
}
printf("Sum= %d",sum); return
0;
}
Output
Enter number of students: 3 Enter marks of student1: 12 Enter marks of student2: 31 Enter marks of
student3: 2
Sum=45
Figure 1.5
#include
<stdio.h>intmain()
{
float a[2][2], b[2][2], c[2][2];
inti,j;
printf("Enter the elements of 1st matrix\n");
/* Reading two dimensional Array with the help of two for loop. If there was an array of 'n'
dimension, 'n' numbers of loops are needed for inserting data to array.*/
for(i=0;i<2;++i)
for(j=0;j<2;++j)
{
printf("Enter a%d%d: ",i+1,j+1);
scanf("%f",&a[i][j]);
}
printf("Enter the elements of 2nd matrix\n");
for(i=0;i<2;++i)
for(j=0;j<2;++j)
{
printf("Enter b%d%d: ",i+1,j+1);
scanf("%f",&b[i][j]);
}
for(i=0;i<2;++i)
for(j=0;j<2;++j)
{
/* Writing the elements of multidimensional array using loop. */
c[i][j]=a[i][j]+b[i][j]; /* Sum of corresponding elements of two arrays. */
Dept. of CSE, ATMECE Page 23
DS(18CS32)
}
printf("\nSum Of Matrix:");
for(i=0;i<2;++i)
for(j=0;j<2;++j)
{
printf("%.1f\t",c[i][j]);
if(j==1) /* To display matrix sum inorder.
*/printf("\n");
}
return 0;
}
Output
Enter the elements of 1st matrix
Enter a11: 2
Enter a12: 0.5
Enter a21: -1.1
Enter a22: 2
Enter the elements of 2nd matrix
Enter b11: 0.2
Enter b12: 0
Enter b21: 0.23
Enter b22: 23
Sum of Matrix:
2.2 0.5
-0.9 25.0
#include<stdio.h>
#include<stdlib.h>int
a[20],b[20],c[40];
intm,n,p,val,i,j,key,pos,temp;
/*Function
Prototype*/ void
create();
void display();
void insert();
search(); void
merge(); void
sort();
int main()
printf("\n\n--------Menu-----------\n");
printf("1.Create\n");
printf("2.Display\n"); printf("3.Insert\n");
printf("4.Delete\n"); printf("5.Search\n");
printf("6.Sort\n"); printf("7.Merge\n");
printf("8.Exit\n");
printf("-----------------------");
scanf("%d",&choice); switch(choice)
case1: create();
break;
case 2:
display(); break;
case 3:
insert();
break;
case 4:
del();
break;
case 5:
search();
break;
case 6:
Dept. of CSE, ATMECE Page 26
DS(18CS32)
sort();
break;
case 7:
merge();
break;
case 8:
exit(0);
break;
default:
printf("\nInvalid choice:\n");
break;
}while(choice!=8);
return 0;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
}//end of create()
int i;
for(i=0;i<n;i++){
printf("%d\t",a[i]);
}//end of display()
scanf("%d",&pos);
scanf("%d",&val);
for(i=n-1;i>=pos;i--)
a[i+1]=a[i];
a[pos]=val;
n=n+1;
}//end of insert()
scanf("%d",&pos);
val=a[pos];
for(i=pos;i<n-1;i++)
a[i]=a[i+1];
n=n-1;
}//end of delete()
scanf("%d",&key);
for(i=0;i<n;i++)
if(a[i]==key)
break;
if(i==n)
}//end of serach()
for(i=0;i<n-1;i++)
for(j=0;j<n-1-i;j++)
if(a[j]>a[j+1])
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
display();
}//end of sort
scanf("%d",&m);
for(i=0;i<m;i++)
scanf("%d",&b[i]);
for(i=0,j=0;i<n;i++,j++)
c[j]=a[i];
for(i=0;i<m;i++,j++)
c[j]=b[i];
p=n+m;
merging:\n"); for(i=0;i<p;i++)
printf("%d\t",c[i]);
}//end of merge
Below shown C program accepts a matrix of order mXn and verifies whether it is a sparse
matrix or not.
#include <stdio.h>
void main ()
{
staticint m1[10][10];
inti,j,m,n;
int counter=0;
printf ("Enter the order of the matix\n");
scanf ("%d %d",&m,&n);
printf ("Enter the co-efficients of the matix\n");
for (i=0;i<m;++i)
{
for (j=0;j<n;++j)
{
scanf ("%d",&m1[i][j]);
if (m1[i][j]==0)
{
++counter;
}
}
}
if (counter>((m*n)/2))
{
printf ("The given matrix is sparse matrix \n");
}
else
printf
("The
given
matrix is
not a
sparse
matrix
\n");
1.13 Polynomials
Polynomials come under the section Algebra in Mathematics. A polynomial is an expression of
finite length constructed from variables, constants and non-negative integer exponents. The
operations addition, subtraction and multiplication determine its entire structure. Polynomials are
used in a wide variety of problems where they are called as polynomial equations.
An example of a polynomial is 3x2+2x+7; here, the total number of terms is 3. The coefficients
of each term are 3, 2, 7 and degrees 2, 1, 0 respectively.
While adding two polynomials, following cases need to be considered.
1. When the degrees of corresponding terms of the two polynomials are same:
This is the normal case when corresponding coefficients of each term can be added directly. For
7x3+9x2+12
-------------------
12x3+11x2+19 is a simple addition where all the degrees of the corresponding terms are same.
2. When the degrees of corresponding terms of the polynomials aredifferent:
Here, the term with the larger degreepre-dominates.
9x4+5x3+ +2x
3x4+ +4x2+7x
------------------------
12x4+5x3+4x2+9x
Below shown C program accepts two polynomials and performs addition operation on them.
#include<stdio.h>
main()
{
int a[10], b[10], c[10],m,n,k,i,j,p,count=0;
clrscr();
printf("\n\tPolynomial Addition\n");
printf("\t===================\n");
printf("\n\tEnter the no. of terms of the polynomial:");
scanf("%d", &m);
printf("\n\tEnter the degrees and coefficients:"); for
(i=0;i<2*m;i++)
scanf("%d", &a[i]); printf("\n\tFirst
polynomial is:");
for(i=0;i<2*m;i=i+2)
{
printf("%dX^%d+",a[i],a[i+1]);
}
printf("\b ");
printf("\n\n\n\tEnter the no. of terms of 2nd polynomial:");
scanf("%d", &n);
printf("\n\tEnter the degrees and co-efficients:");
for(j=0;j<2*n;j++)
scanf("%d", &b[j]); printf("\n\tSecond
polynomial is:"); for(j=0;j<2*n;j=j+2)
{
printf("%dX^%d+",b[j],b[j+1]);
}
printf("\b ");
i=j=k=1;
while (m>0 && n>0)
{
if(a[i]==b[j])
{
c[k-1]=a[i-1]+b[j-1];
c[k]=a[i];
count+=2; m--;
n--;
i+=2;
j+=2;
}
else if(a[i]>b[j])
{
c[k-1]=a[i-1];
c[k]=a[i];
count+=2; m--;
i+=2;
}
Dept. of CSE, ATMECE Page 38
DS(18CS32)
else
{
c[k-1]=b[j-1];
c[k]=b[j];
count+=2; n--;
j+=2;
} k+=2;
}
while (m>0)
{
c[k-1]=a[i-1];
c[k+1]=a[i];
count+=2; k+=2;
i+=2; m--;
}
while (n>0)
{
c[k-1]=b[j-1];
c[k+1]=b[j];
count+=2;
k+=2;
j+=2;
n--;
}
printf("\n\n\n\n\tSum of the two polynomials is:");
for(k=0;k<count;k=k+2)
{
printf("%dX^%d+",c[k],c[k+1]);
}
printf("\b ");
Dept. of CSE, ATMECE Page 39
DS(18CS32)
return 0;
}
1.14 Dynamically allocated arrays
Usually array at the time of its declaration gets it predefined size. Bounding to this size,
programmers will have to find out solution for several problems. For example, if SIZE value is
100, the program can be used to sort a collection up to 100 numbers. If the user wishes to sort
more than 100 numbers, we have to change the definition of SIZE using some larger value and
recompile the program. It becomes little tedious for someone to rethink on this number. Hence
the concept, Dynamic Arrays.
Let us follow the below program to understand the concept of dynamically allocated arrays with
the help of Dynamic Memory Allocation functions (described in 1.14)
#include <stdio.h>
void main(void)
{
int i,*list,n,p;
printf("Enter array size\n");
scanf("%d",&n);
malloc(n, sizeof(int));
printf("Contents and address of Reserved memory blocks for the array\n");
for(i=0;i<n;i++)
printf("%d\t%u\n",*(list+i),&*(list+i));
printf("Enter array elements\n");
for(i=0;i<n;i++) scanf("%d",&*(list+i));
printf("Entered array elements\n");
for(i=0;i<n;i++) printf("%d\n",*(list+i));
realloc(list,p * sizeof(int));
printf("Contents and address of Reserved memory blocks for the array\n");
for(i=0;i<p;i++)
printf("%d\t%u\n",*(list+i),&*(list+i));
printf("Enter the elements\n");
for(i=n;i<p;i++) scanf("%d",&*(list+i));
printf("Updated array:\n"); for(i=0;i<p;i++)
printf("%d\t%u\n",*(list+i),&*(list+i));
list=NULL;
free(list);
printf("%d\n",*(list+i));
}
malloc(n, sizeof(int)); allocates n blocks of memory locations to hold integer data.
realloc(list,p * sizeof(int)); resizes n to pwhere p>n and allocates p number of memory locations
without disturbing the contents of older locations. The above program displays the status of array
before and after memory allocation toit.
#include <stdio.h>
#include
<stdlib.h>intmain()
{
int **p;
int m, n, i, j;
printf("Enter number of rows and columns: ");
}
}
for(i = 0; i < m; i++)
{
for(j = 0; j < n; j++)
{
printf("%d",*(*p+i)+j);
}
printf("\n");
}
/* Deallocate memory */ for(i
= 0; i < m; i++)
{
free(p[i]); /* Rows */
}
free(p); /* Row pointers */
printf("Memory contents of the array after deallocation...\n"); for(i
Dept. of CSE, ATMECE Page 42
DS(18CS32)
= 0; i < m; i++)
{
for(j = 0; j < n; j++)
{
printf("%d",*(*p+i)+j);
}
printf("\n");
}
return 0;
}
Applications of Arrays
1. Arrays are used in sorting and searching methods
2. Arrays are used to represent graphs in the form of matrix
3. Arrays can be used in CPU Scheduling
4. Arrays can be used to demonstrate Stack and Queue data structures
1.15 Strings
Strings are one-dimensional array of characters terminated by a null character '\0'. Thus a null-
terminated string contains the characters that comprise the string followed by a null. The
following declaration and initialization create a string consisting of the word "Hello". To hold
the null character at the end of the array, the size of the character array containing the string is
one more than the number of characters in the word "Hello."
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
If you follow the rule of array initialization then you can write the above statement as follows −
char greeting[] = "Hello";
Following is the memory presentation of the above defined string in C
Note: Actually, you do not place the null character at the end of a string constant. The C
compiler automatically places the '\0' at the end of the string when it initializes the array.
strcmp(s1, s2):- Returns 0 if s1 and s2 are the same; less than 0 if s1<s2; greater
than 0 if s1>s2.
strstr(s1, s2); Returns a pointer to the first occurrence of string s2 in string s1.
compiles code written in a programming language into an executable form. The size of array
you have declared initially can be sometimes insufficient and sometimes more than required.
Dynamic memory allocation allows a programmer to obtain more memory space, while
running or to release space when no space is required.
Although, C language inherently does not have any technique to allocate memory dynamically,
there are 4 library functions under "stdlib.h" for dynamic memory allocation.
malloc() Allocates requested size of bytes and returns a pointer to first byte of allocated space
Allocates space for array elements, initializes to zero and then returns a pointer to
calloc()
memory
Here, ptr is pointer of cast-type. The malloc() function returns a pointer to an area of memory
with size of byte size. If the space is insufficient, allocation fails and returns NULL pointer.
ptr=(int*)malloc(100*sizeof(int));
This statement will allocate either 200 or 400 according to size of int 2 or 4 bytes respectively
and the pointer points to the address of first byte ofmemory.
calloc(): The name calloc stands for "contiguous allocation". The only difference between
malloc() and calloc() is that, malloc() allocates single block of memory whereas calloc() allocates
multiple blocks of memory each of same size and sets all bytes tozero.
Syntax of calloc()
ptr=(cast-type*)calloc(n,element-size);
This statement will allocate contiguous space in memory for an array of n elements. For
example:
ptr=(float*)calloc(25,sizeof(float));
This statement allocates contiguous space in memory for an array of 25 elements each of size of
float, i.e, 4 bytes.
realloc(): The C library function void *realloc(void *ptr, size_t size) attempts to resize the
memory block pointed to by ptr that was previously allocated with a call to malloc or calloc.
Declaration
Following is the declaration for realloc() function.
Parameters
ptr -- This is the pointer to a memory block previously allocated with malloc, calloc or realloc
to be reallocated. If this is NULL, a new block is allocated and a pointer to it is returned by
thefunction.
size -- This is the new size for the memory block, in bytes. If it is 0 and ptr points to an
existing block of memory, the memory block pointed by ptr is deallocated and a NULL
pointer isreturned.
This function returns a pointer to the newly allocated memory, or NULL if the request fails.
Example
The following example shows the usage of realloc() function.
#include <stdio.h>
#include
<stdlib.h>intmain()
char *str;
/* Reallocating memory */
str = (char *) realloc(str, 25);
strcat(str, "swamy");
return(0);
Output
free(): Dynamically allocated memory with either calloc() or malloc() does not get return on its
own. The programmer must use free() explicitly to release space.
syntax of free( )
e.g.: free(ptr);
1.18 Outcome
Apply the concepts of arrays, structures and unions wherever required.
Identify the applications of different types of data structures
Module – II
STRUCTURE
2.0 Introduction
2.1 Objective
2.2 Stack
2.3 Operations on Stack
2.3.1 Stack Representation
2.3.2 Array representation of stack
2.4 Representing stack using dynamic arrays
2.5 Polish Expressions (PN)
2.6 Reverse Polish Expressions (RPN)
2.7 Infix to postfix conversion
2.8 Evaluation of Postfix Expression
2.9 Infix to prefix conversion
2.10 Recursion
2.11 Tower of Hanoi Problem
2.12 Ackerman’s Recursive Function
2.13 Dynamic Implementation of stack
2.14 Queues
2.15 Queue Variants: Circular Queue
2.16 Queue Variants: Priority Queue
2.17 Queue Variants: Double Ended (De-Queue)
2.18 Assignment Questions
2.19 Outcomes
2.0 Introduction
This module gives overview of stack, different stack representation. Different polish
notations are discussed. Methodology for infix to postfix conversion, evaluation of postfix
expression, and infix to prefix conversion is discussed in detail. The recursion is explained with
tower of Hanoi problem and Ackerman’s Recursive Function as examples. The concepts of
queues are highlighted.
2.1 Objective
Understand the concepts of stack, queues.
Understand the methodology of infix to postfix conversion, evaluation of postfix
expression, and infix to prefix conversion.
Understand the usage of recursive functions.
2.2 Stack
A Stack is data structure in which addition of new element or deletion of existing element always
takes place at a same end. This end is known as the top of the stack. That means that it is
possible to remove elements from a stack in reverse order from the insertion of elements into the
stack.
One other way of describing the stack is as a last in, first out (LIFO) abstract data type and linear
data structure. Pictorial representation of the same is shown below
PUSH POP
40 TOP
[3]
30
[2]
20
[1]
[0] 10
Push Function in C
void push()
{
int n;
printf("\n Enter item in stack");
scanf("%d",&n);
if(top==size-1)
{
printf("\nStack is Full");
}
else
{
top=top+1;
stack[top]=n;
}
}
Pop Function in C
void pop()
{
int item;
if(top==-1)
{
printf("\n Stack is empty");
}
else
{
item=stack[top];
printf("\n item popped is=%d", item);
top--;
}
}
#include <stdio.h>
#include <stdlib.h>
struct node
{
int info;
struct node *ptr;
}*top,*top1,*temp;
void push(int data);
void pop();
void display();
void destroy();
void main()
{
int no, ch, e;
printf("\n 1 - Push");
printf("\n 2 - Pop");
printf("\n 3 - Exit");
printf("\n 4 - Dipslay");
printf("\n 5 - Destroy stack");
top=NULL;
while (1)
{
printf("\n Enter choice : ");
scanf("%d", &ch);
switch (ch)
{
case 1:
printf("Enter data : ");
scanf("%d", &no);
push(no);
break;
case 2:
pop();
break;
case 3:
exit(0);
case 4:
display();
break;
case 5:
destroy();
break;
default :
printf(" Wrong choice, Please enter correct choice ");
break;
}
}
}
void push(int data)
{
if (top == NULL)
{
top =(struct node *)malloc(1*sizeof(struct node));
top->ptr = NULL;
top->info = data;
}
else
{
temp =(struct node *)malloc(1*sizeof(struct node));
temp->ptr = top;
temp->info = data;
top = temp;
}
}
/* Display stack elements */
void display()
{
top1 = top;
if (top1 == NULL)
{
printf("Stack is empty");
return;
}
while (top1 != NULL)
{
printf("%d ", top1->info);
top1 = top1->ptr;
}
}
/* Pop Operation on stack */
void pop()
{
top1 = top;
if (top1 == NULL)
{
printf("\n Error : Trying to pop from empty stack");
return;
}
else
top1 = top1->ptr;
printf("\n Popped value : %d", top->info);
free(top);
top = top1;
}
void destroy()
{
top1 = top;
while (top1 != NULL)
{
top1 = top->ptr;
free(top);
top = top1;
top1 = top1->ptr;
}
free(top1);
top = NULL;
printf("\n All stack elements destroyed");
}
Polish notation (PN), also known as normal Polish notation (NPN), Polish prefix notation or
simply prefix notation is a form of notation for logic, arithmetic, and algebra. Its distinguishing
feature is that it places operators to the left of their operands
3 –2 -3 2
3 * 2+5 +* 3 25
(12 - 3 ) /3 / -12 3 3
Reverse Polish Notation (RPN), sometimes referred to as postfix notation, is a way of writing
mathematical expressions where each operand is preceded by the two operators it applies to and
looks something like 2 5 3 + * instead of (5 + 3 ) * 2
Well, it turns out that it is easier/more efficient for computers to parse an RPN expression than
an infix one. In fact, if you look at the code underlying most calculators you'd find that most of
them take the infix expressions that we write and first convert them to postfix before evaluating
them. Meta calculator's graphing and scientific calculators both do exactly this.
Examples
3-2 32-
3 * 2+5 532*+
(12 - 3 ) /3 12 3 - 3 /
Infix notation is easy to read for humans, whereas pre-/postfix notation is easier to parse for a
machine. The big advantage in pre-/postfix notation is that there never arise any questions like
operator precedence.
For example, consider the infix expression 1 # 2 $ 3. Now, we don't know what those operators
mean, so there are two possible corresponding postfix expressions: 1 2 # 3 $ and 1 2 3 $ #.
Without knowing the rules governing the use of these operators, the infix expression is
essentially worthless.
Or, to put it in more general terms: it is possible to restore the original (parse) tree from a pre-
/postfix expression without any additional knowledge, but the same isn't true for infix
expressions.
− × ÷ 15 − 7 + 1 1 3 + 2 + 1 1 =
− × ÷ 15 − 7 2 3+2+11=
− × ÷ 15 5 3+2+11=
−×3 3+2+11=
−9 +2+11=
−9 +22 =
−9 4 =
Answer is 5
A/B^C-D
Parse the expression from left to right. Since ^ has precedence than other operators in the
expression, consider its operands and convert it into immediate postfix form.
Since, / has higher precedence, consider its operands and convert it into its immediate postfix
notation. i.e.,AE1/-D. Now say the converted portion as E2 and rewrite the expression
E2-D
ABC^/D-
That’s it!!
Computer converts the same expression using stack and here comes one of the main applications
of stack. The below shown tabular conversion would best explain the overall process.
Current
Expression Stack Output Comment
Symbol
Initial
A/B^C-D NULL – Initially Stack is Empty
State
Try it yourself
E2-D
Finally, it becomes - E2D. [Recall; E2 -> /AE1 , & E1 -> ^BC]
Now its time to substitute, AE1/D-
-/A^BCD
That’s it!!
2.10 Recursion
A function that calls itself is known as recursive function. And, this technique is
known as recursion.
The recursion continues until some condition is met to prevent it. To prevent infinite
recursion, if...else statement (or similar approach) can be used where one branch
makes the recursive call and other doesn't.
An example program in C
#include <stdio.h>
int sum(int n);
int main()
{
int number, result;
printf("Enter a positive integer: ");
scanf("%d", &number);
result = sum(number);
printf("sum=%d", result);
}
int sum(int n)
{
if (n!=0)
return n + sum(n-1); // sum() function calls itself
else
return n;
}
Initially, the sum() is called from the main() function with number passed as an
argument.
Suppose the value of n is 3 init ially. During next function call, 2 is passed to
the sum() function. In next function call, 1 is passed to the function. This process
continues until n is equal to 0.
When n is equal to 0, there is no recursive call and the sum of integers is returned to
the main() function.
#include <stdio.h>
int factorial(int);
void main()
int result,num;
scanf("%d",&num);
result=factorial(num);
printf("%d",result);
if(ele==0)
return 1;
else
return (ele*factorial(ele-1));
Output
Factorial of 6 = 720
Suppose the user entered 6. Initially, the multiplyNumbers() is called from the main() function
with 6 passed as an argument. Then, 5 is passed to the multiplyNumbers() function from the
same function (recursive call). In each recursive call, the value of argument nis decreased by 1.
When the value of n is less than 1, there is no recursive call.
60
G.C.D of 366 and 60 is 6.
In the above program, towers (…) is the function that shows its execution in a recursive manner.
OK, now let us see the problem constraints of Tower of Hanoi and let us try to understand how it
can be addressed non-programmatically….
2.11 Problem: Move all the disks over to the rightmost tower, one at a time, so that they end up
in the original order on that tower. You may use the middle tower as temporary storage, but at no
time during the transfer should a larger disk be on top of a smaller one.
3
2
1
3
2
1
What you are observing is the problem (in the upper part) and its solution (in the lower part). If
we manually try to work it out keeping all the constraints in mind, the sequence of steps that one
would perform for 3 disks:
O K….. now that you got an idea of how this problem can be solved manually. But, we being
programmers should find out solution with computer as a tool. Let’s do that…..
A small note to you all, it would be better if you take a copy (print or handwritten) of the
program shown above in your hand for analysis purpose otherwise you need to scroll several
times.
3, A, C, B Pushed to
Stack TOP
n f t a
Pushed to
2, A, B, C Stack TOP
3, A, C, B
Not stack
contents n f t a
Once again, the condition is checked i.e., if(num==1) ? it’s not again.
One more time recursive call takes place:
towers(num - 1, frompeg, auxpeg, topeg); i.e., num-1 = 1; frompeg=A; auxpeg=C; topeg=B;
Now, these parameter values will be mapped to the parameters in (1)
Resulting into as below,
num = num-1 = 1; frompeg = frompeg = A; topeg = auxpeg = C; auxpeg = topeg = B;
Now the stack content would look like this
Pushed to
1, A, C, B Stack TOP
2, A, B, C
3, A, C, B
n f t a
This time the condition satisfies i.e., num =1 now. Top of the stack will be popped as recursion
gets a break. The statement inside will get executed and the following statement would get
printed
2, A, B, C Pushed to
Stack TOP
3, A, C, B
n f t a
Figure X
Pushed to
3, A, C, B Stack TOP
n f t a
Now with the popped parameter values, second function call invokes the function.
towers(num - 1, auxpeg, topeg, frompeg); num-1 = 1; auxpeg = C; topeg = B; frompeg = A;
[referring to stack top of figure X ]
Now, the above parameter values will be mapped to the parameters in (1)
Resulting into as below,
num = num-1 = 1; frompeg = auxpeg = C; topeg = topeg = B; auxpeg = frompeg = A;
1, C, B, A Pushed to
Stack TOP
3, A, C, B
n f t a
Since the condition if(num == 1) satisfies, the print statement would get executed by taking the
popped parameters.
Hence, we see
Move disk 1 from peg C to peg B; num=1, frompeg = C, topeg = B
Stack contents now,
Pushed to
3, A, C, B Stack TOP
n f t a
Figure Y
Finally, the stack top is popped and the parameters are used for executing the print statement
outside the condition. Stack is empty now.
n f t a
Now, the above parameter values will be mapped to the parameters in (1)
Resulting into as below,
num = num-1 = 2; frompeg = auxpeg = B; topeg = topeg = C; auxpeg = frompeg = A;
Now the stack content would look like this
Pushed to
2, B, C, A Stack TOP
n f t a
The condition will not hold because num = 2. Now, the first recursive call invokes the function
by supplying parameters onto the stack.
towers(num - 1, frompeg, auxpeg, topeg); i.e., num-1 = 1; frompeg=B; auxpeg=C; topeg=A;
Now, the above parameter values will be mapped to the parameters in (1)
Resulting into as below,
num = num-1 = 1; frompeg = frompeg = B; topeg = auxpeg = C; auxpeg = topeg = A;
Now the stack content would look like this
Pushed to
2, B, C, A Stack TOP
Gets n f t a
Popped 1, B, A, C
Figure Z
The ‘if’ condition holds, hence print statement executes popping the stack.
int mainackerman()
{
int m,n;
scanf("%d %d",&m,&n);
printf("%d %d",ackerman(m,n),w);
return 0;
}
top->ptr = NULL;
top->info = data;
}
else
{
temp =(struct node *)malloc(1*sizeof(struct node));
temp->ptr = top;
temp->info = data;
top = temp;
}
}
/* Display stack elements */
void display()
{
top1 = top;
if (top1 == NULL)
{
printf("Stack is empty");
return;
}
while (top1 != NULL)
{
printf("%d ", top1->info);
top1 = top1->ptr;
}
}
/* Pop Operation on stack */
void pop()
{
top1 = top;
if (top1 == NULL)
{
printf("\n Error : Trying to pop from empty stack");
return;
}
else
top1 = top1->ptr;
printf("\n Popped value : %d", top->info);
free(top);
top = top1;
}
void destroy()
{
top1 = top;
while (top1 != NULL)
{
top1 = top->ptr;
free(top);
top = top1;
top1 = top1->ptr;
}
free(top1);
top = NULL;
printf("\n All stack elements destroyed");
}
2.14 Queues
Queue is an abstract data structure, somewhat similar to Stack. In contrast to Stack, queue is
opened at both end. One end is always used to insert data, that end is referred to as REAR and
the operation is called enqueue and the other end referred to as FRONT, is used to remove data
and the operation is called dequeue. Queue follows First-In-First-Out methodology, i.e., the data
item stored first will be accessed first.
A real world example of queue can be a single-lane one-way road, where the vehicle enters first,
exits first. More real-world example can be seen as queues at ticket windows & bus-stops.
Queue [6]: 10 20 30 40 50
REAR
FRONT
The representation of queue is using arrays. Initially, FRONT & REAR indices are initialized to
-1. As elements are inserted, rear is incremented by 1 and as elements are deleted, front is
incremented by 1. Shaded cells in the above figure are empty. If an element is added, it sits in the
immediate next cell to rear and rear shifts right by one cell (i.e., rear++). Similarly if an element
is deleted, front shifts right by one cell (i.e. front++).
Applications of Queue
Queue, as the name suggests is used whenever we need to have any group of objects in an order
in which the first one coming in, also gets out first while the others wait for their turn, like in the
following scenarios:
1. Serving requests on a single shared resource, like a printer, CPU task scheduling etc.
2. In real life, Call Center phone systems will use Queues, to hold people calling them in an
order, until a service representative is free.
3. Handling of interrupts in real-time systems. The interrupts are handled in the same order as
they arrive, First come first served.
Array Implementation of a Queue
#include <stdio.h>
#define MAX 50
int queue_array[MAX];
int rear = - 1;
int front = - 1;
main()
{
int choice;
while (1)
{
printf("1.Insert element to queue \n");
printf("2.Delete element from queue \n");
printf("3.Display all elements of queue \n");
printf("4.Quit \n");
printf("Enter your choice : ");
scanf("%d", &choice);
switch (choice)
{
case 1:
insert();
break;
case 2:
delete();
break;
case 3:
display();
break;
case 4:
exit(1);
default:
printf("Wrong choice \n");
} /*End of switch*/
} /*End of while*/
} /*End of main()*/
insert()
{
int add_item;
if (rear == MAX - 1)
printf("Queue Overflow \n");
else
{
if (front == - 1)
/*If queue is initially empty */
front = 0;
printf("Inset the element in queue : ");
scanf("%d", &add_item);
rear = rear + 1;
queue_array[rear] = add_item;
}
} /*End of insert()*/
delete()
{
if (front == - 1 || front > rear)
{
printf("Queue Underflow \n");
return ;
}
else
{
printf("Element deleted from queue is : %d\n", queue_array[front]);
front = front + 1;
}
} /*End of delete() */
display()
{
int i;
if (front == - 1)
printf("Queue is empty \n");
else
{
printf("Queue is : \n");
for (i = front; i <= rear; i++)
printf("%d ", queue_array[i]);
printf("\n");
}
}
In a standard queue data structure re-buffering problem occurs for each de queue operation. To
solve this problem by joining the front and rear ends of a queue to make the queue as a circular
queue.
Basic Operations
1. Insert / enqueue − add an item to the rear of the queue.
int main()
{
printf("1.Insert\n2.Delete\n3.Display\n4.Exit\n");
while(1)
{
printf("Enter your choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1: if(Q_full())
printf("Priority Queue is Full\n");
else
insert();
break;
case 2: if(Q_Empty())
printf("Priority Queue Empty\n");
else
delet();
break;
case 3: if(Q_Empty())
printf("Priority Queue Empty\n");
else
display();
break;
case 4: exit(0);
}
}
}
void insert()
{
int ele;
}
void display()
{
printf("Elements of Priority Queue...");
for(i=front;i<=rear;i++)
printf("%d\t",queue[i]);
}
Rear Front
RADAR inserted R A D A R
Rear Front
Verification R A D A R
2.19 Outcomes
Know the methodology for infix to postfix conversion, evaluation of postfix expression,
and infix to prefix conversion.
Identify the applications of stacks and queues.
Familiarized with the usage of recursive function.
Module III
STRUCTURE
3.0 Introduction
3.1 Objective
3.2 Linked List
3.3 Linked list types
3.4 Linked List Representation
3.5 Operations on Linked Lists
3.5.1 Inserting a node
3.5.2 Deleting a node
3.6 Types of Linked Lists
3.7 Header Linked List
3.8 Doubly Linked list operations
3.9 Assignment Questions
3.10 Outcomes
3.0 Introduction
This module discusses the linked list data structures, operations on linked list. Different
types of liked list are explained in detail. The header linked list and its usage is highlighted. The
concept of doubly linked list is discussed.
3.1 Objective
Understand the linked list data structures and its operation
Understand the usage of header linked list and doubly linked list operations
Linked list is the collection of inter connected nodes with a head node representing the first node
and a tail node representing the last node of it. A node can be viewed as a block consisting of
two major fields : a data field and a pointer field. The pointer field is used to interconnect nodes
of a list. Below diagram depicts the linked list setup.
Tail
NULL
There are few variants of linked lists. Below diagram shows a brief classification of Linked
Lists.
Linked List
Regarding these variants of LL, explanations and examples are given in subsequent sections of
the notes.
A simple representation of singly linked list would look like the below:
struct node {
int data;
struct node *next; };
new node
Initially, the pointer field of the first node in singly linked list would contain NULL value.
Instruction that makes it is: newnode->next = NULL;
Note: Structure variables’ fields of self referential type are accessed through -> (arrow
operator)
Now, let us try to understand few conventions w.r.t linked lists. Consider below given list.
10 NULL
head; tail
tail = head; // assigning the reference of head to tail. This means both head and tail are referring
to the same node.
Now, let us add a new node to this list.
Newnode = (struct node *) malloc (1 * sizeof(struct
node)); newnode->data = 20; newnode->next =
NULL;
10 NULL 10 NULL
10 1008h 20 NULL
50 1000h
head; newnode
Suppose we wish to insert a node at the end, following set of instruction are to be executed.
Take a temporary variable of type struct node, traverse the list until you reach the last node (i.e
tail )
while(temp->next !=NULL)
{
temp=temp->next;
}
temp->next = newnode;
tail = newnode;
Now let us see how to insert a node at a particular position in the list. For this, we need to ask
user to specify after which node in the list he would want to insert. Call it as “key” node. This
can be realized as below:
temp
10 1008h 20 1016h 30 1040h 40 1032h
80 NULL
Key = 30 100 1032h
Newnode (1040h) (1032h)
Take a temporary variable of type struct node, traverse the list until you reach the desired node
(i.e 30)
while(temp->data !=key)
100 NULL
{
temp=temp->next; newnode (1040h)
}
newnode->next = temp->next;
temp->next = newnode;
3.5.2 Deleting a node: A node in the list can be deleted using the standard function free ( ). Let us
see an example to understand delete operations on linked list.
10 1008h 20 1024h 30 NULL 40 NULL
head (1000h) temp2 (1008h) temp(1016h) tail (1024h)
Let us try to delete node with 30 data value.
Take two temporary variables and position them to key node and the previous node of it.
Below C program creates a singly linked list and performs few operations like insert, delete,
display, search, insert and delete at specific positions in the list.
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct node{
int data;
struct node *ptr;
};
struct node *head, *last,*temp, *temp2;
void create();
void delet();
void dele_spec();
void display();
void spec_ins();
int search(int);
int num,con=1,ch,key,f;
void main()
{
clrscr();
head=NULL;
printf("1.Create\n2.Delete\n3.Delete Specific\n4.Insert After Specific node\n5.Display\n6.
Search\n7.Exit\n");
while(1)
{
printf("Enter choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1: printf("Enter number\n");
scanf("%d",&num);
create();
break;
case 2: delet();
break;
case 3: dele_spec();
break;
case 4: spec_ins();
break;
case 5: display();
break;
case 6: printf("Enter the node data to be searched\n");
scanf("%d",&key);
f=search(key);
if(f==1) printf("NODE FOUND\n");
else printf("NODE NOT FOUND\n");
break;
case 7: exit(0);
}
}
}
void create()
{
if(head==NULL)
{
head = (struct node*)malloc(1*sizeof(struct node));
head->data=num;
head->ptr=NULL;
last=head;
}
else
{
temp= (struct node*)malloc(1*sizeof(struct node));
temp->data=num;
last->ptr=temp;
temp->ptr=NULL;
last=temp;
}
}
void delet()
{
if(head==NULL)
{
printf("List is empty\n");
}
else
{
temp=head->ptr;
free(head);
head=temp;
}
}
void dele_spec()
{
int key;
printf("Enter the node to be deleted\n");
scanf("%d",&key);
temp=head;
temp2=head;
while(temp->data!=key)
{
temp=temp->ptr;
}
while(temp2->ptr!=temp)
{
temp2=temp2->ptr;
}
if(temp->ptr==NULL)
{
temp2->ptr=NULL;
free(temp);
last=temp2;
}
else
{
temp2->ptr=temp->ptr;
free(temp);
}
}
void spec_ins()
{
int key;
printf("Enter the node info next to which to be inserted\n");
scanf("%d",&key);
printf("Enter data for newnode\n");
scanf("%d",&num);
temp2= (struct node*)malloc(1*sizeof(struct node));
temp2->data=num;
temp=head;
while(temp->data!=key)
{
temp=temp->ptr;
}
temp2->ptr=temp->ptr;
temp->ptr=temp2;
}
void display()
{
if(head==NULL)
{
printf("List empty\n");
}
else
{
temp=head;
while(temp!=NULL)
{
printf("%d\t",temp->data);
temp=temp->ptr;
}
}
}
Doubly Linked List : In a doubly linked list, each node contains two links the first link points to
the previous node and the next link points to the next node in the sequence.
Circular Linked List : In the circular linked list the last node of the list contains the address of
the first node and forms a circular chain.
Header linked list is similar to Singly linked List but the difference is that in this type of list,
there exists a special node called “head”, which either contains information regarding total nodes
in the list or the address of the last node in the whole list.
C Program to implement header linked list is shown below
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct node{
int data;
struct node *ptr;
};
struct node *head, *last,*temp, *newnode;
void create();
void delet();
void display();
int num,count=0,ch;
void main()
{
clrscr();
head=NULL;
printf("1.Create\n2.Delete\n3.Display\n4.Exit\n");
while(1)
{
printf("Enter choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1: if(head==NULL)
{
head = (struct node*)malloc(1*sizeof(struct node));
head->data=count;
head->ptr=NULL;
last=head;
}
printf("Enter number\n");
scanf("%d",&num);
create();
break;
case 2: delet();
break;
case 3: display();
break;
case 4: exit(0);
}
}
}
void create()
{
newnode = (struct node*)malloc(1*sizeof(struct node));
newnode->data=num;
newnode->ptr=NULL;
last->ptr=newnode;
last=newnode;
count++;
head->data=count;
}
void delet()
{
if(head->data==0)
{
printf("List is empty\n");
}
else
{
temp=head;
while(temp->ptr!=last)
{
temp=temp->ptr;
}
free(last);
last =temp;
last->ptr=NULL;
}
count--;
head->data=count;
}
void display()
{
if(head==NULL)
{
printf("List empty\n");
}
else
{
temp=head->ptr;
while(temp!=NULL)
{
printf("%d\t",temp->data);
temp=temp->ptr;
}
}
printf("\nHeader Information:%d\n",head->data);
}
temp->next=top;
top=temp;
}
}
void display()
{
struct Node *var=top;
if(var!=NULL)
{
printf("\nElements are as:\n");
while(var!=NULL)
{
printf("\t%d\n",var->Data);
var=var->next;
}
printf("\n");
}
else
printf("\nStack is Empty");
}
int main(int argc, char *argv[])
{
int i=0;
top=NULL;
printf(" \n1. Push to stack");
printf(" \n2. Pop from Stack");
printf(" \n3. Display data of Stack");
printf(" \n4. Exit\n");
while(1)
{
printf(" \nChoose Option: ");
scanf("%d",&i);
switch(i)
{
case 1:
{
int value;
printf("\nEnter a valueber to push into Stack: ");
scanf("%d",&value);
push(value);
display();
break;
}
case 2:
{
popStack();
display();
break;
}
case 3:
{
display();
break;
}
case 4:
{
struct Node *temp;
while(top!=NULL)
{
temp = top->next;
free(top);
top=temp;
}
exit(0);
}
default:
{
printf("\nwrong choice for operation");
}
}
}
}
Merging of two lists
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
};
void insert_list1();
void insert_list2();
void display();
void merge_list();
struct node *list1, *list2,*list3,*temp1,*temp2,*temp3,*temp4;
void main()
{
int ch;
clrscr();
printf("1 for insert in first linklist\n");
printf("2 for insert in second linklist\n");
printf("3 for display first & second linklist\n");
void merge_list()
{
temp1=list1;
temp2=list2;
while(temp1!=NULL || temp2!=NULL)
{
temp3=(struct node*)malloc(1*sizeof(struct node));
if(list3==NULL)
{
list3=temp3;
temp4=temp3;
}
if(temp1->data<temp2->data)
{
temp3->data=temp1->data;
temp4->next=temp3;
temp4=temp3;
temp1=temp1->next;
}
else
{
temp3->data=temp2->data;
temp4->next=temp3;
temp4=temp3;
temp2=temp2->next;
}
if(temp2==NULL)
{
while(temp1!=NULL)
{
temp3=(struct node*)malloc(1*sizeof(struct node));
temp3->data=temp1->data;
temp4->next=temp3;
temp4=temp3;
temp1=temp1->next;
}
break;
}
if(temp1==NULL)
{
while(temp2!=NULL)
{
temp3=(struct node*)malloc(1*sizeof(struct node));
temp3->data=temp2->data;
temp4->next=temp3;
temp4=temp3;
temp2=temp2->next;
}
break;
}
}
temp3->next=NULL;
}
void insert_list1()
{
struct node *new;
if(list1==NULL)
{
list1=(struct node *)malloc(sizeof(struct node));
printf("Enter the info");
scanf("%d",&list1->data);
list1->next=NULL;
temp1=list1;
}
else
{
new=(struct node *)malloc(sizeof(struct node));
printf("Enter the info");
scanf("%d",&new->data);
new->next=NULL;
temp1->next=new;
temp1=temp1->next;
}
}
void insert_list2()
{
struct node *new;
if(list2==NULL)
{
list2=(struct node *)malloc(sizeof(struct node));
printf("Enter the info");
scanf("%d",&list2->data);
list2->next=NULL;
temp2=list2;
}
else
{
new=(struct node *)malloc(sizeof(struct node));
printf("Enter the info");
scanf("%d",&new->data);
new->next=NULL;
temp2->next=new;
temp2=temp2->next;
}
}
void display()
{
temp1=list1;
temp2=list2;
printf("\nThe Information of First linklist:");
while(temp1!=NULL)
{
printf("%d ",temp1->data);
temp1=temp1->next;
}
printf("\nThe Information of Second linklist:");
while(temp2!=NULL)
{
printf("%d ",temp2->data);
temp2=temp2->next;
}
temp3=list3;
printf("\nMerged List:");
while(temp3!=NULL)
{
printf("%d ",temp3->data);
temp3=temp3->next;
}
}
Reversing a Singly Linked List
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
};
void insert_list();
void display();
void revers();
temp1=temp1->next;
}
temp->next=temp1;
temp=temp1;
}
temp=tail;
head->next=NULL;
printf("Reversed list: ");
while(temp!=NULL)
{
printf("%d ",temp->data);
temp=temp->next;
}
}
void insert_list()
{
struct node *new;
if(head==NULL)
{
head=(struct node *)malloc(sizeof(struct node));
printf("Enter the info");
scanf("%d",&head->data);
head->next=NULL;
tail=temp=head;
}
else
{
new=(struct node *)malloc(sizeof(struct node));
printf("Enter the info");
scanf("%d",&new->data);
new->next=NULL;
temp->next=new;
temp=temp->next;
tail=temp;
}
temp1=head;
printf("Created list: ");
while(temp1!=NULL)
{
printf("%d ",temp1->data);
temp1=temp1->next;
}
}
Singly Circular Linked List Operations
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
struct node{
int data;
struct node *ptr;
};
struct node *newnode, *front,*rear, *temp;
void create();
void display();
void delet();
int num,ch;
void main()
{
front=rear=NULL;
while(1)
{
printf("Enter choice\n");
scanf("%d",&ch);
switch(ch)
{
case 1: printf("Enter number\n");
scanf("%d",&num);
create();
break;
case 2: delet();
break;
case 3: display();
break;
case 4: exit(0);
}
}
}
void create()
{
newnode = (struct node*)malloc(1*sizeof(struct node));
newnode->data=num;
if(rear==NULL)
front=rear=newnode;
else
{
rear->ptr=newnode;
rear=newnode;
}
rear->ptr=front;
}
void delet()
{
if(front==NULL)
printf("List is empty\n");
else if(front==rear)
{
printf("Element deleted is %d",front->data);
front=NULL;
}
else
{
temp=front;
printf("Deleted element is %d",temp->data);
temp=temp->ptr;
free(front);
front=temp;
rear->ptr=front;
}
}
void display()
{
if(front==NULL)
{
printf("List empty\n");
}
else
{
temp=front;
while(temp!=rear)
{
printf("%d\t",temp->data);
temp=temp->ptr;
}
}
printf("%d\n",temp->data);
}
Adding and evaluating Polynomials using Circular Linked List
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <math.h>
struct node{
int coeff;
int expo;
struct node *ptr;
};
struct node *head1,*head2,*head3, *temp,*temp1,*temp2,*temp3,*list1,*list2,*list3;
struct node *dummy1,*dummy2;
void create_poly1(int , int);
void create_poly2(int , int);
void display();
void add_poly();
void eval_poly(int );
int n,ch;
int c,e,i;
void main()
{
int x;
list1=list2=NULL;
printf("1.Create first polynomial\n2.Create Second Polynomial\n3.Display both the
polynomials\n");
eval_poly(x);
break;
case 6:exit(0);
}
}
}
void create_poly1(int c, int e)
{
dummy1=(struct node*)malloc(1*sizeof(struct node));
dummy1->coeff=0;
dummy1->expo=0;
dummy1->ptr=list1;
if(list1==NULL)
{
list1=(struct node*)malloc(1*sizeof(struct node));
list1->coeff=c;
list1->expo=e;
list1->ptr=list1;
head1=list1;
head1->ptr=dummy1;
}
else
{
temp=(struct node*)malloc(1*sizeof(struct node));
temp->coeff=c;
temp->expo=e;
head1->ptr=temp;
temp->ptr=dummy1;
head1=temp;
while((temp1!=dummy1)&&(temp2!=dummy2))
{
temp=(struct node*)malloc(1*sizeof(struct node));
if(list3==NULL)
{
list3=temp;
head3=list3;
}
if(temp1->expo==temp2->expo)
{
temp->coeff=temp1->coeff+temp2->coeff;
temp->expo=temp1->expo;
temp->ptr=list3;
head3->ptr=temp;
head3=temp;
temp1=temp1->ptr;
temp2=temp2->ptr;
}
else if(temp1->expo>temp2->expo)
{
temp->coeff=temp1->coeff;
temp->expo=temp1->expo;
temp->ptr=list3;
head3->ptr=temp;
head3=temp;
temp1=temp1->ptr;
}
else
{
temp->coeff=temp2->coeff;
temp->expo=temp2->expo;
temp->ptr=list3;
head3->ptr=temp;
head3=temp;
temp2=temp2->ptr;
}
}
if(temp1==dummy1)
{
while(temp2!=dummy2)
{
temp=(struct node*)malloc(1*sizeof(struct node));
temp->coeff=temp2->coeff;
temp->expo=temp2->expo;
temp->ptr=list3;
head3->ptr=temp;
head3=temp;
temp2=temp2->ptr;
}
}
if(temp2==dummy2)
{
while(temp1!=dummy1)
{
temp=(struct node*)malloc(1*sizeof(struct node));
temp->coeff=temp1->coeff;
temp->expo=temp1->expo;
temp->ptr=list3;
head3->ptr=temp;
head3=temp;
temp1=temp1->ptr;
}
}
}
void display()
{
temp1=list1;
temp2=list2;
temp3=list3;
printf("\nPOLYNOMIAL 1:");
while(temp1!=dummy1)
{
printf("%dX^%d+",temp1->coeff,temp1->expo);
temp1=temp1->ptr;
}
printf("\b ");
printf("\nPOLYNOMIAL 2:");
while(temp2!=dummy2)
{
printf("%dX^%d+",temp2->coeff,temp2->expo);
temp2=temp2->ptr;
}
printf("\b ");
printf("\n\nSUM OF POLYNOMIALS:\n");
while(temp3->ptr!=list3)
{
printf("%dX^%d+",temp3->coeff,temp3->expo);
temp3=temp3->ptr;
}
printf("%dX^%d\n",temp3->coeff,temp3->expo);
void eval_poly(int x)
{
int result=0;
temp1=list1;
temp2=list2;
while(temp1!=dummy1)
{
result+=(temp1->coeff)*pow(x,temp1->expo);
temp1=temp1->ptr;
}
printf("Polynomial 1 Evaluation:%d\n",result);
result=0;
while(temp2!=dummy2)
{
result+=(temp2->coeff)*pow(x,temp2->expo);
temp2=temp2->ptr;
}
printf("Polynomial 2 Evaluation:%d\n",result);
}
3.8 Doubly Linked list operations
Below shown C program demonstrates basic operations on Doubly Linked List
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int count=0;
struct stud
{
long long int ph;
int sem;
char name[15],usn[15],brnch[8];
struct stud *next;
}*head=NULL,*tail=NULL,*temp=NULL,*temp1;
void create(long long int n,int s,char na[20],char u[15],char b[5])
{
if(head==NULL)
{
head=(struct stud*)malloc(1*sizeof(struct stud));
head->ph=n;
head->sem=s;
strcpy(head->name,na);
strcpy(head->usn,u);
strcpy(head->brnch,b);
head->next=NULL;
tail=head;
count++;
}
else
{
temp=(struct stud*)malloc(1*sizeof(struct stud));
temp->ph=n;
temp->sem=s;
strcpy(temp->name,na);
strcpy(temp->usn,u);
strcpy(temp->brnch,b);
temp->next=NULL;
tail->next=temp;
tail=temp;
count++;
}
}
void display()
{
temp1=head;
if(temp1==NULL)
{
printf("\nlist is empty\n");
}
else
{
printf("student details are as follows:\n");
while(temp1!=NULL)
{
printf("-----------------------\n");
printf("NAME:%s\nUSN:%s\nBRANCH:%s\nSEM:%d\nPHONE NO.:%lld\n",temp1-
>name,temp1->usn,temp1->brnch,temp1->sem,temp1->ph);
printf("-----------------------\n");
temp1=temp1->next;
}
printf("no. of nodes=%d\n",count);
}
}
void insert_head(long long int n,int s,char na[15],char u[15],char b[8])
{
temp=(struct stud*)malloc(1*sizeof(struct stud));
temp->ph=n;
temp->sem=s;
strcpy(temp->name,na);
strcpy(temp->usn,u);
strcpy(temp->brnch,b);
temp->next=head;
head=temp;
count++;
}
void insert_tail(long long int n,int s,char na[15],char u[15],char b[8])
{
temp=(struct stud*)malloc(1*sizeof(struct stud));
temp->ph=n;
temp->sem=s;
strcpy(temp->name,na);
strcpy(temp->usn,u);
strcpy(temp->brnch,b);
tail->next=temp;
temp->next=NULL;
tail=temp;
count++;
}
void delete_head()
{
temp1=head;
if(temp1==NULL)
{
printf("list is empty\n");
}
else
{
head=head->next;
printf("deleted node is:\n");
printf("-----------------------\n");
printf("NAME:%s\nUSN:%s\nBRANCH:%s\nSEM:%d\nPHONE NO.:%lld\n",temp1-
>name,temp1->usn,temp1->brnch,temp1->sem,temp1->ph);
printf("-----------------------\n");
free(temp1);
count--;
}
}
void delete_tail()
{
temp1=head;
if(temp1==NULL)
{
printf("list is empty\n");
}
while(temp1->next!=tail)
{
temp1=temp1->next;
}
printf("deleted node is:\n");
printf("-----------------------\n");
printf("NAME:%s\nUSN:%s\nBRANCH:%s\nSEM:%d\nPHONE NO.:%lld\n",tail->name,tail-
>usn,tail->brnch,tail->sem,tail->ph);
printf("-----------------------\n");
free(tail);
tail=temp1;
tail->next=NULL;
count--;
}
void main()
{
int choice;
long long int ph;
int sem;
char name[20],usn[15],brnch[5];
printf("--------MENU----------\n");
3.10 Outcome
Identify the application of linked list.
Familiarized with different linked list operation
MODULE 4: TREES
STRUCURE
4.0 Introduction
4.1 Objective
4.2 Definition
4.3 Terminology
4.4 Representation of Trees
4.4.1 List Representation
4.4.2 Left Child-Right Sibling Representation
4.4.3 Representation as a Degree-Two Tree
4.5 Binary Trees
4.5.1 Different Kinds of Binary Tree
4.6 Properties of Binary Trees
4.7 Binary Tree Representation
4.7.1 Array Representation
4.7.2 Linked Representation
4.8 Binary Tree Traversals
4.8.1 Inorder
4.8.2 Preorder
4.8.3 Postorder
4.8.4 Iterative Inorder
4.8.5 Level-Order Traversal
4.9 Additional Binary Tree Operations
4.10 Threaded Binary Tree
4.10.1 Inorder Traversal of A Threaded Binary Tree
4.10.2 Inserting a Node into a Threaded Binary Tree
4.11 Assignment Questions
4.12 Outcomes
4.0 Introduction
This module gives the overview of tree data structures, representation of trees using list.
Concepts of binary tree and its representation of array and linked representation are discussed in detail.
Different binary tree traversal is discussed with example. Threaded binary trees are highlighted.
4.1 Objective
Understand the concept of tree data structure, binary trees and its operation.
Understand the different methodology for binary tree traversal.
4.2 DEFINITION
A tree is a finite set of one or more nodes such t h a t
There is a specially designated node called root.
The remaining nodes are partitioned into n >= 0 disjoint set T1,…,Tn, where each of
these sets is a tree. T1,…,Tn are called the subtrees of the root.
4.3 TERMINOLOGY
Node: The item of information plus the branches to other nodes
Degree: The number of subtrees of a node
Degree of a tree: The maximum of the degree of the nodes in the tree.
Terminal nodes (or leaf): nodes that have degree zero or node with no successor
Nonterminal nodes: nodes that don’t belong to terminal nodes.
Parent and Children: Suppose N is a node in T with left successor S1 and right
successor S2, then N is called the Parent (or father) of S1 and S2. Here, S1 is called
left child (or Son) and S2 is called right child (or Son) of N.
Siblings: Children of the same parent are said to be s i b l i n g s .
Edge: A line drawn from node N of a T to a successor is called an edge
Path: A sequence of consecutive edges from node N to a node M is called a p a t h .
Ancestors of a node: All the nodes along the path from the root to that node.
The level of a node: defined by letting the root be at level zero. If a node is at level l,
then it children are at level l+1.
Height (or depth): The maximum level of any node in the tree
Figure (A)
1. List Representation
2. Left Child- Right Sibling Representation
3. Representation as a Degree-Two tree
The tree can be represented as a List. The tree of figure (A) could be written as the list.
(A (B (E (K, L), F), C (G), D (H (M), I, J) ) )
Tree node is represented by a memory node that has fields for the data and pointers to the tree
node's children
Since the degree of each tree node may be different, so memory nodes with a varying number of
pointer fields are used.
For a tree of degree k, the node structure can be represented as below figure. Each child field is
used to point to a subtree.
The below figure show the node structure used in the left child-right sibling representation
Ex: In Figure (A), the leftmost child of A is B, and the leftmost child of D is H.
The closest right sibling of B is C, and the closest right sibling of H is I.
Choose the nodes based on how the tree is drawn. The left child field of each node points
to its leftmost child (if any), and the right sibling field points to its closest right sibling (if
any).
Figure (D) shows the tree of Figure (A) redrawn using the left child-right sibling representation.
To obtain the degree-two tree representation of a tree, simply rotate the right-sibling pointers in a
left child-right sibling tree clockwise by 45 degrees. This gives us the degree-two tree displayed
in Figure (E).
In the degree-two representation, a node has two children as the left and right children.
1. Skewed Tree
A skewed tree is a tree, skewed to the left or skews to the right.
or
It is a tree consisting of only left subtree or only right subtree.
A tree with only left subtrees is called Left Skewed Binary Tree.
A tree with only right subtrees is called Right Skewed Binary Tree.
Figure (a): Skewed binary tree Figure (b): Complete binary tree
The following tree is its extended binary tree. The circles represent internal nodes, and square
represent external nodes.
Every internal node in the extended tree has exactly two children, and every external node is a
leaf. The result is a complete binary tree
Proof:
(1) The proof is by induction on i.
Induction Base: The root is the only node on level i = 1. Hence, the maximum number of nodes
on level i =1 is 2i-1 = 20 = 1.
Induction Hypothesis: Let i be an arbitrary positive integer greater than 1. Assume that the
maximum number of nodes on level i -1is 2i-2
Induction Step: The maximum number of nodes on level i -1 is 2i-2 by the induction hypothesis.
Since each node in a binary tree has a maximum degree of 2, the maximum number of nodes
on level i is two times the maximum number of nodes on level i-1, or 2i-1
Proof: Let n1 be the number of nodes of degree one and n the total number of nodes.
Since all nodes in T are at most of degree two, we have
n = n0 + n1+ n2 (1)
Count the number of branches in a binary tree. If B is the number of branches, then n
=B + 1.
All branches stem from a node of degree one or two. Thus,
B =n 1+ 2n2.
Hence, we obtain
n = B + 1= n 1+ 2n2 + 1 (2)
Subtracting Eq. (2) From Eq. (1) and rearranging terms, we get
n0 = n2 +1
Below figure shows the array representation for both the trees of figure (a).
For complete binary tree the array representation is ideal, as no space is wasted.
For the skewed tree less than half the array is utilized.
4.8.1 Inorder: Inorder traversal calls for moving down the tree toward the left until you cannot go
further. Then visit the node, move one node to the right and continue. If no move can be done, then
go back one more node.
Let ptr is the pointer which contains the location of the node N currently being scanned.
L(N) denotes the leftchild of node N and R(N) is the right child of node N
Recursion function:
The inorder traversal of a binary tree can be recursively defined as
void inorder(treepointerptr)
{
if (ptr)
{
inorder (ptr→leftchild);
printf (“%d”,ptr→data);
inorder (ptr→rightchild);
}
}
4.8.2 Preorder: Preorder is the procedure of visiting a node, traverse left and continue. When
you cannot continue, move right and begin again or move back until you can move right and
resume.
Recursion function:
The Preorder traversal of a binary tree can be recursively defined as
Visit the root
Traverse the left subtree in preorder.
Traverse the right subtree in preorder
4.8.3 Postorder: Postorder traversal calls for moving down the tree towards the left until you
can go no further. Then move to the right node and then visit the node and continue.
Recursion function:
The Postorder traversal of a binary tree can be recursively defined as
Traverse the left subtree in postorder.
Traverse the right subtree in postorder.
Visit the root
void postorder(treepointerptr)
{
if (ptr)
{
postorder (ptr→leftchild);
postorder (ptr→rightchild);
printf (“%d”,ptr→data);
}
}
2. Testing Equality
This operation will determin the equivalance of two binary tree. Equivalance binary tree have
the same strucutre and the same information in the corresponding nodes.
This function will return TRUE if two trees are equivalent and FALSE if they are not.
The satisfiablity problem for formulas of the propositional calculus asks if there is an
assignment of values to the variable that causes the value of the expression to be true.
The algorithm to determine satisfiablity is to let (x1, x2, x3) takes on all the possible
combination of true and false values to check the formula for each combination.
For n value of an expression, there are 2n possible combinations of true and false
For example n=3, the eight combinations are (t,t,t), (t,t,f), (t,f,t), (t,f,f), (f,t,t), (f,t,f), (f,f,t),
(f,f,f).
The algorithm will take O(g 2n), where g is the time to substitute values for x1, x2,… xn and
evaluate the expression.
Node structure:
For the purpose of evaluation algorithm, assume each node has four fields:
In the linked representation of any binary tree, there are more null links than actual pointers.
These null links are replaced by the pointers, called threads, which points to other nodes in the
tree.
In above figure the new threads are drawn in broken lines. This tree has 9 node and 10 0 -links
which has been replaced by threads.
Node Structure:
The node structure is given in C declaration
The complete memory representation for the tree of figure is shown in Figure C
The variable root points to the header node of the tree, while root →leftChild points to the start of
the first node of the actual tree. This is true for all threaded trees. Here the problem of the loose
threads is handled by pointing to the head node called root.
4.12. Outcome
Familiarized with different tree traversal methodologies.
Identify the applications of tree data structure.
Module V
STRUCTURE
5.0 Introduction
5.1 Objective
5.2 Definitions & Concept
5.3 Graph Terminologies
5.4 Basic Operations on Graphs
5.5 Representing Graph Data Structure
5.6 Complete Graphs and Connected Graphs
5.7 Graph Traversal Methods
5.7.1 Depth First Search (DFS)
5.7.2 Breadth First Traversal (BFS)
5.8 Sorting
5.8.1 Insertion Sort
5.9 Assignment Questions
5.10 Outcomes
5.0 Introduction
This module gives the overview of graphs and its terminologies. The DFS and BS traversal
methods are discussed in detail with examples. The different sorting techniques are explained in
detail. Different types of graph are highlighted.
5.1 Objective
Understand the graph data structures and its operations.
Understand the different graph traversal methods.
Understand the different sorting techniques.
A graph is a pictorial representation of a set of objects where some pairs of objects are connected
by links. The interconnected objects are represented by points termed as vertices, and the links
that connect the vertices are called edges.
Formally, a graph is a pair of sets (V, E), where V is the set of vertices and E is the set of edges,
connecting the pairs of vertices. Take a look at the following graph –
V = {a, b, c, d, e}
Vertex – Each node of the graph is represented as a vertex. In the following example,
the labeled circle represents vertices. Thus, A to E are vertices.
Edge – Edge represents a path between two vertices or a line between two vertices. In
the following example, the lines from A to B, B to C, and so on represents edges.
Adjacency – Two node or vertices are adjacent if they are connected to each other
through an edge. In the following example, B is adjacent to A, C is adjacent to B, and so
on.
Path – Path represents a sequence of edges between the two vertices. In the following
example, ABCD represents a path from A to D.
Self – loop: A self-loop is an edge that connects a vertex to itself. A has self loop
A B
E D
Figure a
A B
E D
Figure b
Add Edge – Adds an edge between the two vertices of the graph.
Graphs can be represented using a two dimensional array or with the help of linked lists.
If two dimensional array is used to represent a graph, such matrix is referred to as adjacency
matrix.
If linked list representation is used then such list is referred to as adjacency list.
To represent a graph in computer’s memory, we first need to understand what type of graph it is.
There are different types of graphs: - directed, undirected, weighted and un weighted graphs.
1. Directed graphs: These are the graphs that have directed edges, i.e., edges with
direction. Figure b is an example for this.
2. Un Directed Graphs: These are the graphs that have undirected edges, i.e., edges with
no direction. Figure a is an example for this.
3. Weighted Graphs: These are the graphs that contains edges with weights (values).
5
A B 6
8 C
7
D 3
E
9
Figure c
4. Unweighted Graphs: These are the graphs that contains edges with no weights (values).
Figure a and b are un weighted.
Combinations of above graphs would result in graphs such as weighted – directed, weighted
– un directed, Directed – un weighted graphs
Now, let us represent a directed graph using adjacency matrix concept. Consider figure b.
Basically, the size of adjacency matrix will be equal to the number of vertices in the graph. In
the above graph, there are 5 vertices therefore size is 5x5.
0 1 0 0 0 A B
0 0 1 0 0
C
0 0 0 0 0
0 0 1 0 0 E D
1 0 0 1 0
Figure b
If in the graph, there exists an edge between two vertices, it is denoted 1 in the matrix
otherwise 0.
To represent an undirected graph, the matrix shows symmetry property. Consider the below
graph.
A B
0 1 0 0 1
1 0 1 1 0
C
0 1 0 1 0
0 1 1 0 1
E D
1 0 0 1 0
Figure d
To represent a weighted directed graph, little modification in the representation procedure has to
be done.
5
A B 6
8 C
7
D 3
E
9
Figure c
Here, if there exists an edge between two vertices then in the matrix its value is
denoted otherwise a infinity ( or larger value like 999). All diagonal values will be 0.
Below is the adjacency list representation. Vertex 0 has edge to vertex 1 and vertex 4. Hence there
A complete graph is any graph where there's an edge between every pair of vertices in the
graph. Figure x is complete.
In a connected graph, there is a path between any given pair of vertices. Figure y is connected
A B
E D
Figure x
A B
E D
Figure y
Basically, there are two graph traversal methods – Depth First Search & Breadth First Search.
The depth first traversal is similar to the preorder traversal of a binary tree. An initial or source
vertex is identified to start traversing, then from that vertex any one vertex which is adjacent to
the current vertex is traversed i.e. only one adjacent vertex is traversed from the vertex which
had been traversed last.
The general algorithm is:
for each vertex v in the graph
if v is not visited
Start the depth first traversal at v
The general algorithm to do a depth first traversal at a given node v is:
1. Mark node v as visited
2. Visit the node
3. For each vertex u adjacent to v
a. if u is not visited
b. start the depth first traversal at u
c. Clearly, this is a recursive algorithm.
Consider the below shown graph, chose A as source vertex and apply DFS. The resulting
traversal sequence
A BDC E
This algorithm uses stack data structure.
A B
E D
Figure b
As in the case of the depth first traversal, because it might not be possible to traverse the entire
graph from a single vertex, the breadth first traversal also traverses the graph from each vertex
that is not visited. Starting at the first vertex, the graph is traversed as much as possible; we then
go to the next vertex that has not been visited. In other words it can be stated as all vertices that
are adjacent to the current vertex are traversed first. To implement the breadth first search
algorithm, we use a queue.
if v is not visited
b. Mark v as visited
to u if w is not visited
Mark w as visited
Consider the
below graph
A B
E D
Figure b
A is visited, then vertices adjacent to A are inserted into the queue. B is in queue now. Adjacent
to B are C & D so D & C are in queue. Adjacent to D is E therefore E will be in the queue.
When all the vertices in the queue are removed, the final sequence will be obtained
A B C D E
#include <stdio.h>
#include <stdlib.h>
int a[20][20],q[20],visited[20],reach[10],n,i,j,f=0,r=-1,count=0;
void bfs(int v)
{
for(i=1;i<=n;i++)
if(a[v][i] && !visited[i])
q[++r]=i;
if(f<=r)
{
visited[q[f]]=1;
bfs(q[f++]);
}
}
void dfs(int v)
{
int i;
reach[v]=1;
for(i=1;i<=n;i++)
{
Dept. of CSE, ATMECE Page 10
DS(18CS32)
if(visited[i])
printf("%d\t",i);
}
break;
case 2:dfs(1);
if(count==n-1)
printf("\n Graph is connected");
else
printf("\n Graph is not connected");
break;
case 3: exit(0);
}
}
5.8 Sorting
Sorting is a technique in which elements are arranged either in ascending or descending order.
There are number of sorting algorithms. Here, majorly three sorting algorithms are identified and
explained.
1. Insertion Sort
2. Radix Sort
#include<stdio.h>
int main(){
int i,j,s,temp,a[20];
for(i=1;i<s;i++){
temp=a[i];
j=i-1;
while((temp<a[j])&&(j>=0)){
a[j+1]=a[j];
j=j-1;
}
a[j+1]=temp;
}
return 0;
}
5.10 Outcomes
Identify the applications of graph data structure.
Familiarized with graph traversal methods, DFS and BFS.
Familiarized with different sorting technologies.