Data Structures
21CSC201J
UNIT- 1
Introduction:
• Programming in C - Primitive data types, Structures, Self-referential
structures, Pointers and structures, Dynamic memory allocation, Matrix
multiplication;
• Data Structure – Definition, Types, ADT, Operations; Mathematical
notations - Big O, Omega and Theta, Complexity – Time, Space, Trade
off.
Data vs. Information
Data: A value or a group of values is known as data.
Example: CSE, SRM, 22-07-2023, Monday, Male, 7548844997,
snagendraprabhu@gmail.com, Y, 99.50
Data is same as in its singular and plural forms
Information: Processed data is known as Information (Data with meaning
associated with it)
Example: I am working in SRM
Today is Monday
My attendance percentage is 99.50
‘Y’ is for Yes
Data structure
• Data Type: the kind/type of data we are using is known as data type.
Basic data types are: int, float, double, char, string
Data structure: A data structure is basically a group of data elements that are put
together under one name, and which defines a particular way of storing and
organizing data in a computer so that it can be used efficiently.
Data structures are widely applied in the following areas:
Compiler design
Operating system
Statistical analysis package
Data Base Management Systems (DBMS)
Numerical analysis
Simulation
Artificial intelligence
Graphics
Introduction to Data Structures
• A data structure is a way of storing data in a computer so
that it can be used efficiently and it will allow the most
efficient algorithm to be used.
• A data structure should be seen as a logical concept that
must address two fundamental
• concerns.
I. First, how the data will be stored, and
II. Second, what operations will be performed on it.
Types of Data Structure
Examples:
Primitive Data structure:
• The primitive data structures are the basic data types
that are available in most of the programming languages
and can be manipulated directly by machine
instructions.
• The primitive data types are used to represent single
values.
• They are
• Integer,
• Float and Double ,
• Character ,
• String
• Boolean
Primitive Data structure:
• Integer: This is used to represent a number without
decimal point.
• Eg: 12, 90
• Float and Double: This is used to represent a number
with decimal point.
• Eg: 45.1, 67.3
• Character : This is used to represent single character
• Eg: ‘C’, ‘a’
• String: This is used to represent group of characters.
• Eg: "College of Engineering"
• Boolean: This is used represent logical values either true
or false.
Non-Primitive Data structure
• The data structures that are derived from primary data
types are known as non-Primitive data types. These data
types are used to store group of values.
• These once again can be classified as
• Linear data structures
• Non linear data structures
Linear data structure
• Linear data structure
• A data structure is called linear if all of its elements are
arranged in the linear order. In linear data structures, the
elements are stored in non-hierarchical way where each
element has the successors and predecessors except the first
and last element. Linear order  each and every element will
have attachment with first and last values.
• Types of Linear Data Structures are given below:
• Arrays
• Linked List
• Stack
• Queue
Non Linear data structure
• This data structure does not form a sequence i.e. each
item or element is connected with two or more other
items in a non-linear arrangement. The data elements
are not arranged in sequential structure.
• Types of Non Linear Data Structures are given below:
• Trees
• Graphs
Structures
?
Why we need Structure ?
• Arrays allow to define type of variables that can hold several data
items of the same kind. Similarly structure is another user defined
data type available in C that allows to combine data items of different
kinds.
Structures
• Definition: A structure is defined as a collection of data of
same/different data types. All data items thus grouped are
logically related and can be accessed using variables.
Thus, structure can also be defined as a group of variables
of same or different data types. The variables that are
used to store the data are called members of the
structure or fields of the structure.
•In C, the structure is identified by the keyword struct.
Structures- Example
• The structure definition with tag name is called tagged
structure. The tag name is the name of the structure.
The syntax of tagged structure is shown below:
Structures- Example
• Ex: The structure definition to hold the student
information such as name, roll_number and
average_marks can be written as shown below:
Structure declaration
• “How to declare a Variable in structure?”
• As variables are declared before they are used in the
function, the structures are also should be declared
before they are used. A structure can be declared
using different ways as shown below:
Declaring structure variable
• 1st way:
• Let's see the example to declare the structure variable by
struct keyword. It should be declared within the main function.
struct employee
{ int id;
char name[50];
float salary;
};
Now write given code inside the main() function.
struct employee e1, e2;
The variables e1 and e2 can be used to access the values
stored in the structure.
Declaring structure variable
• 2nd way:
• Let's see another way to declare variable at the time of
defining the structure.
struct employee
{ int id;
char name[50];
float salary;
}e1,e2;
Which approach is good
• If number of variables are not fixed, use the 1st
approach. It provides you the flexibility to declare the
structure variable many times.
• If no. of variables are fixed, use 2nd approach. It saves
your code to declare a variable in main() function.
Example- Create struct variables
• Suppose you want to keep track of your books in a
library. You might want to track the following
attributes about each book −
• Title
• Author
• Subject
• Book ID
Example- Create struct variables
struct Books
{
char title[50];
char author[50];
char subject[100];
int book_id;
} b1;
#include <stdio.h>
struct student
{
char name[40]; // Student name
int roll; // Student enrollment
float CPI; // Student mobile number
int backlog;
};
int main()
{
struct student student1; // Simple structure
variable
// Input data in structure members using dot
operator
printf("Enter Student Name:");
scanf("%s", student1.name);
printf("Enter Student Roll Number:");
scanf("%d", &student1.roll);
printf("Enter Student CPI:");
scanf("%f", &student1.CPI);
printf("Enter Student Backlog:");
scanf("%d", &student1.backlog);
// Display data in structure members using dot
operator
printf("nStudent using simple structure variable.
n");
printf("Student name: %sn", student1.name);
printf("Student Enrollment: %dn", student1.roll);
printf("Student CPI: %fn", student1.CPI);
printf("Student Backlog: %in", student1.backlog);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Enter Student Name:aaa
Enter Student Roll Number:111
Enter Student CPI:7.89
Enter Student Backlog:0
Student using simple structure
variable.
Student name: aaa
Student Enrollment: 111
Student CPI: 7.890000
Student Backlog: 0
Program Output
Write a program to read and display student information using structure.
Nested Structure in C
• A structure inside another structure is called nested
structure.
• C provides us the feature of nesting one structure
within another structure.
• For example,
• we may need to store the address of an entity employee in a
structure. The attribute address may also have the subparts
as street number, city, state, and pin code. Hence, to store
the address of the employee, we need to store the address
of the employee into a separate structure and nest the
structure address into the structure employee.
The structure can be nested in the following ways.
• By separate structure
• By Embedded structure
Separate structure
• Here, we create two structures, but the dependent structure should be used inside
the main structure as a member. Consider the following example.
struct Date
{
int dd;
int mm;
int yyyy;
};
struct Employee
{
int id;
char name[20];
struct Date doj;
}emp1;
As you can see, doj (date of joining) is the variable of type Date. Here doj is used as a
member in Employee structure.
Embedded structure
• The embedded structure enables us to declare the structure inside the structure.
Hence, it requires less line of codes but it can not be used in multiple data structures.
Consider the following example.
struct Employee
{
int id;
char name[20];
struct Date
{
int dd;
int mm;
int yyyy;
}doj;
}emp1;
Accessing Nested Structure
• We can access the member of the nested structure by
Outer_Structure.Nested_Structure.member as given
below:
emp1.doj.dd
emp1.doj.mm
emp1.doj.yyyy
Example for nested structure
#include<stdio.h>
struct address
{
char city[20];
int pin;
char phone[14];
};
struct employee
{
char name[20];
struct address add;
};
void main ()
{
struct employee emp;
printf("Enter employee information?n");
scanf("%s %s %d %s",emp.name,emp.add.city, &emp.add.pin, emp.add.phone);
printf("Printing the employee information....n");
printf("name: %snCity: %snPincode: %dnPhone: %s",emp.name,emp.add.city,emp.add.pin,emp.add.phone);
}
Array of Structures
• Why use an array of structures?
• Consider a case, where we need to store the data of 5 students,
we can easily create 5 variable and do it.
• However, the complexity of the program will be increased if there
are 20 students. In that case, we will have to declare 20 different
structure variables and store them one by one. This will always be
tough since we will have to declare a variable every time we add a
student.
• Array of Structures in C
• An array of structres in C can be defined as the collection of multiple
structures variables where each variable contains information about
different entities. The array of structures in C are used to store
information about multiple entities of different data types. The array of
structures is also known as the collection of structures.
Array of Structures in C
#include<stdio.h>
#include <string.h>
struct student{
int rollno;
char name[10];
};
int main(){
int i;
struct student st[5];
printf("Enter Records of 5 students");
for(i=0;i<5;i++){
printf("nEnter Rollno:");
scanf("%d",&st[i].rollno);
printf("nEnter Name:");
scanf("%s",&st[i].name);
}
printf("nStudent Information List:");
for(i=0;i<5;i++){
printf("nRollno:%d, Name:%s",st[i].rollno,st[i].name);
}
return 0;
}
Why do we require a Self-referential structure?
• Self-referential structure plays a vital role in the linked list, trees, graphs, and many
more data structures.
• By using the structure, we can easily implement these data structures efficiently.
• For defining a particular node, the structure plays a very important role.
• In a linked list, the structure is used to store the data information and the address of the
next node in the given linked list.
• Mainly the data part is of integer type, and the link address part is of pointer type, which
holds the address of the next node, so that it can for the Link ultimately.
Pointers
• The pointer in C language is a variable which stores
the address of another variable. This variable can be
of type int, char, array, function, or any other pointer.
• Consider the following example to define a pointer
which stores the address of an integer.
• int n = 10;
• int *p = &n;
• // Variable p of type pointer is pointing to the addres
s of the variable n of type integer.
Declaring a pointer
• The pointer in c language can be declared using *
(asterisk symbol).
• Syntax of Pointer
• Datatype *Variable_name
• int *a;//pointer to int
• char *c;//pointer to char
Initialization of C Pointer variable
• Pointer Initialization is the process of assigning
address of a variable to a pointer variable. It contains
the address of a variable of the same data type.
• int a = 10;
• int *ptr; //pointer declaration
• ptr = &a; //pointer initialization
Simple pointer example
#include<stdio.h>
int main(){
int number=50;
int *p;
p=&number; //stores the address of number variable
printf("Address of p variable is %x n",p);
// p contains the address of the number
printf("Value of p variable is %d n",*p);
// As we know that * is used to dereference a pointer therefore if we print
*p, we will get the value stored at the address contained by p.
return 0;
}
Simple pointer example
• #include <stdio.h>
• int main () {
• int var = 20; /* actual variable declaration */
• int *ip; /* pointer variable declaration */
• ip = &var; /* store address of var in pointer variable*/
• printf("Address of var variable: %xn", &var );
• /* address stored in pointer variable */
• printf("Address stored in ip variable: %xn", ip );
• /* access the value using the pointer */
• printf("Value of *ip variable: %dn", *ip );
• return 0;
• }
Structure Pointer
• The structure pointer points to the address of a memory
block where the Structure is being stored. Like a pointer that
tells the address of another variable of any data type (int, char,
float) in memory. And here, we use a structure pointer which
tells the address of a structure in memory by pointing pointer
variable ptr to the structure variable.
• Declare a Structure Pointer
• The declaration of a structure pointer is similar to the
declaration of the structure variable.
• So, we can declare the structure pointer and variable inside
and outside of the main() function. To declare a pointer
variable in C, we use the asterisk (*) symbol before the
variable's name.
•struct structure_name *ptr;
Pointer to structure
struct st {
int i;
float f;
}v1;
struct st *p = &v1;
Structure using pointers Program
#include <stdio.h>
int main() {
struct book {
char name[25];
char author[25];
int callno;
};
struct book b1 = { "Let us C", "ABC", 101 };
struct book *ptr;
ptr = &b1;
printf("Address of b1: %pn", &b1);
return 0;
}
Structure using pointers Program
#include <stdio.h>
int main() {
struct book {
char name[25];
char author[25];
int callno;
};
struct book b1 = { "Let us C", "ABC", 101 };
struct book *ptr;
ptr = &b1;
printf("%s %s %dn", b1.name, b1.author, b1.callno);
printf("%s %s %dn", ptr->name, ptr->author, ptr->callno);
printf("%p %p %pn", &ptr->name,&ptr->author,&ptr->callno);
return 0;
}
Dynamic memory allocation in C
• The concept of dynamic memory allocation in c
language enables the C programmer to allocate
memory at runtime.
• Dynamic memory allocation in c language is possible
by 4 functions of stdlib.h header file.
• malloc()
• calloc()
• realloc()
• free()
Before learning above functions, let's understand the difference
between static memory allocation and dynamic memory allocation.
static memory allocation dynamic memory allocation
memory is allocated at compile time. memory is allocated at run time.
memory can't be increased while
executing program.
memory can be increased while
executing program.
used in array. used in linked list.
Methods used for dynamic memory
allocation.
malloc()
memory allocation
allocates single block of requested memory.
calloc()
Contiguous
Allocation
allocates multiple block of requested memory.
realloc()
reallocation
reallocates the memory occupied by malloc() or
calloc() functions.
free() frees the dynamically allocated memory.
malloc() method
• The “malloc” or “memory allocation” method in C is
used to dynamically allocate a single large block of
memory with the specified size.
• 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)
Example for syntax
• ptr = (int*) malloc (100 * sizeof(int));
• Since the size of int is 4 bytes, this statement will
allocate 400 bytes of memory. And, the pointer ptr
holds the address of the first byte in the allocated
memory.
calloc() method
• “calloc” or “contiguous allocation” method in C is
used to dynamically allocate the specified number of
blocks of memory of the specified type. it is very
much similar to malloc() but has two different points
and these are:
• It initializes each block with a default value ‘0’.
• It has two parameters or arguments as compare to
malloc().
• The syntax of calloc() function is given below:
• ptr=(cast-type*)calloc(number, byte-size)
Example for syntax
• ptr = (float*) calloc(25, sizeof(float));
• This statement allocates contiguous space in memory
for 25 elements each with the size of the float.
realloc() method
• 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)
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)
Sample program – Memory Allocation
#include<stdio.h>
#include<stdlib.h>
int main(){
int n,i,*ptr,sum=0;
printf("Enter number of elements: ");
scanf("%d",&n);
ptr=(int*)malloc(n*sizeof(int)); //memory allocated using malloc
if(ptr==NULL)
{
printf("Sorry! unable to allocate memory");
exit(0);
}
printf("Enter elements of array: ");
for(i=0;i<n;++i)
{
scanf("%d",ptr+i);
sum+=*(ptr+i);
}
printf("Sum=%d",sum);
free(ptr);
return 0;
}
Matrix Multiplication
• In matrix multiplication, it is not necessary that both matrices
must be a square matrix, as in addition and subtraction.
• Suppose we have a matrix A of m×n dimensions and a matrix B
of n×k dimensions, then the resultant matrix will be
of m×k dimensions.
Matrix Multiplication
Matrix Multiplication…
#include<stdio.h>
#include<stdlib.h>
int main(){
int a[10][10],b[10][10],mul[10][10],r,c,i,j,k;
system("cls");
printf("enter the number of row=");
scanf("%d",&r);
printf("enter the number of column=");
scanf("%d",&c);
printf("enter the first matrix element=n");
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
scanf("%d",&a[i][j]);
}
}
printf("enter the second matrix element=n");
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
scanf("%d",&b[i][j]);
} }
printf("multiply of the matrix=n");
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
mul[i][j]=0;
for(k=0;k<c;k++)
{
mul[i][j]+=a[i][k]*b[k][j];
}
}
}
//for printing result
for(i=0;i<r;i++)
{
for(j=0;j<c;j++)
{
printf("%dt",mul[i][j]);
}
printf("n");
}
return 0;
}
• Output
enter the number of row=3
enter the number of column=3
enter the first matrix element=
1 1 1
2 2 2
3 3 3
enter the second matrix element=
1 1 1
2 2 2
3 3 3
multiply of the matrix=
6 6 6
12 12 12
18 18 18
Classification of Data Structures
• Data structures can be classified as
i. Simple data structure
ii. Compound data structure
i. Linear data structure
ii. Non linear data structure
5
8
Data Structure Classification
Operations on data structures
1. Inserting: adding new data items to the given list of data items.
2. Deleting: remove (delete) a particular data item from the given collection of
data items.
3. Searching: find the location of one or more data items that satisfy the given
constraint. Such a data item may or may not be present in the given collection of
data items.
4. Sorting: arranging data elements in specific order like ascending order or
descending order depending on the type of application.
5. Merging: two lists of sorted data items can be combined to form a single list of
sorted data items
Traverse Etc.,
Data Structure Operations
& ADT
Data Structure Operations
• Linked List
- Definition and Declaration (Structure)
- Creation (Head node)
- Insertion
- Deletion
- Search / Traverse
- Types (Single, Double, Circular)
- Applications
Data Structure Operations
• Stack
- Definition and Declaration (Array / List)
- Insertion (Push)
- Deletion (Pop)
- Searching
- Applications
Data Structure Operations
• Queue
- Definition and Declaration (Array / List)
- Insertion ( Enqueue )
- Deletion ( Dequeue)
- Types ( Linear, Circular )
- Applications
Data Structure Operations
• Tree
- Definition and Declaration (Array / List)
- Insertion
- Deletion
- Types ( Binary Tree, Binary Search Tree, AVL Tree, Etc..)
- Applications
Abstract Data Type
• An abstract data type is an abstraction of a data
structure that provides only the interface to which the
data structure must adhere. The interface does not
give any specific details about something should be
implemented or in what programming language.
• In other words, we can say that abstract data types
are the entities that are definitions of data and
operations but do not have implementation details. In
this case, we know the data that we are storing and
the operations that can be performed on the data,
but we don't know about the implementation details.
Let's understand the abstract data type with a real-world example.
• If we consider the smartphone. We look at the high specifications of the
smartphone, such as:
• RAM Size
• Processor
• inch LCD screen
• Dual camera
• Android Version
• The above specifications of the smartphone are the abstract data, and we can also
perform the following operations on the smartphone:
• call(): We can call through the smartphone.
• text(): We can text a message.
• photo(): We can click a photo.
• video(): We can also make a video.
• The smartphone is an entity whose data or specifications and operations are given
above. The abstract/logical view and operations are the abstract or logical views of a
smartphone.
Let us see some operations of ADT in Data structure
• Stack −
• isFull(), This is used to check whether stack is full or not
• isEmpty(), This is used to check whether stack is empty or not
• push(x), This is used to push x into the stack
• pop(), This is used to delete one element from top of the stack
• peek(), This is used to get the top most element of the stack
• size(), this function is used to get number of elements present into the stack
• Queue −
• isFull(), This is used to check whether queue is full or not
• isEmpty(), This is used to check whether queue is empty or not
• Enqueue(x), This is used to add x into the queue at the rear end
• Dequeue(), This is used to delete one element from the front end of the
queue
• size(), this function is used to get number of elements present into the queue
Algorithm Analysis
• The algorithm can be analyzed in two levels, i.e., first is before
creating the algorithm, and second is after creating the
algorithm. The following are the two analysis of an algorithm:
• Priori Analysis: Here, priori analysis is the theoretical
analysis of an algorithm which is done before implementing
the algorithm. Various factors can be considered before
implementing the algorithm like processor speed, which has
no effect on the implementation part.
• Posterior Analysis: Here, posterior analysis is a practical
analysis of an algorithm. The practical analysis is achieved by
implementing the algorithm using any programming
language. This analysis basically evaluate that how much
running time and space taken by the algorithm.
70
Algorithm Analysis and Complexity
• The performances of algorithms can be measured on the scales
of Time and Space.
• The Time Complexity of an algorithm or a program is a
function of the running time of the algorithm or a program.
• The Space Complexity of an algorithm or a program is a
function of the space needed by the algorithm or program to run
to completion.
The Need for Analysis
• Algorithms are often quite different from one another, though the
objective of these algorithms are the same.
• For example, we know that a set of numbers can be sorted using
different algorithms.
• Number of comparisons performed by one algorithm may vary
with others for the same input.
• Hence, time complexity of those algorithms may differ.
• At the same time, we need to calculate the memory space
required by each algorithm.
The Need for Analysis
• Analysis of algorithm is the process of analyzing the problem-solving
capability of the algorithm in terms of the time and size required (the
size of memory for storage while implementation).
• However, the main concern of analysis of algorithms is the required
time or performance. Generally, we perform the following types of
analysis −
• Worst-case − The maximum number of steps taken on any instance of
size a.
• Best-case − The minimum number of steps taken on any instance of
size a.
• Average case − An average number of steps taken on any instance of
size a.
Algorithm Complexity
• The performance of the algorithm can be measured in two
factors:
• Time complexity
• Space complexity
• Time complexity: The time complexity of an algorithm is
the amount of time required to complete the execution. The
time complexity of an algorithm is denoted by the big O
notation. Here, big O notation is the asymptotic notation to
represent the time complexity. The time complexity is mainly
calculated by counting the number of steps to finish the
execution. Let's understand the time complexity through an
example.
Algorithm Complexity
• Time complexity:
sum=0;
// Suppose we have to calculate the sum of n numbers.
for i=1 to n
sum=sum+i;
// when the loop ends then sum holds the sum of the n nu
mbers
return sum;
• In the above code, the time complexity of the loop
statement will be atleast n, and if the value of n increases,
then the time complexity also increases.
Algorithm Complexity
• Space complexity: An algorithm's space complexity is the amount of
space required to solve a problem and produce an output. Similar to the
time complexity, space complexity is also expressed in big O notation.
• For an algorithm, the space is required for the following purposes:
1. To store program instructions
2. To store constant values
3. To store variable values
4. To track the function calls, jumping statements, etc.
• Auxiliary space: The extra space required by the algorithm, excluding
the input size, is known as an auxiliary space. The space complexity
considers both the spaces, i.e., auxiliary space, and space used by the
input.
So,
• Space complexity = Auxiliary space + Input size.
Performance Analysis
• There are many things upon which the performance will
depend.
• Does the program efficiently use primary and Secondary
storage?
• Is the program's running Time acceptable for the task?
• Does it do what we want it to do?
• Does it work correctly according to the specifications of the
task?
• Does the program contain documentation that shows how to
use it and how it works?
• Is the program's code readable?
Performance Analysis
•Time complexity and Space complexity
• We will find best case, worst case and Average case
• For Time complexity we will use two method
• Frequency count or step count
• Asymptotic notation
• For Space complexity we will use method called
• Frequency count or step count
Space Complexity
• The space needed by a program has the following components.
• Instruction space
• Data Space
• Environmental stack space
• Instruction space
• Instruction space is the space needed to store the compiled version of
the program instructions.
• Data space
• Data space is the space needed to store all constant and variable
values. Data space has two components.
• Space needed by constants( ex; 1 and 2 in max of n num algorithm)
and simple variables( such as i, j, n etc).
• Environmental stack space
• The environment stack is used to save information needed to resume
execution of partially completed functions.
• Each time a function is invoked the following data are saved on the
environment stack.
Contd..
Therefore, We can divide the total space needed by a
program into two parts:
i) Fixed Space Requirements (C)
Independent of the characteristics of the problem instance ( I )
• Instruction space
• Data space for simple variables and constants.
ii) Variable Space Requirements (SP(I))
depend on the characteristics of the problem instance ( I )
• Number of inputs and outputs associated with I
• recursive stack space ( formal parameters, local variables, return address ).
• Therefore, the space requirement of any problem P can be written as
S(p)=C +Sp( Instance characteristics )
• Note:
• When analyzing the space complexity of an algorithm, we
concentrate only on estimating
Sp (Instance characteristics ).
• We do not concentrate on estimating fixed part c .
Example-1
1. Algorithm abc (a, b, c)
2. {
3. return a+b+b*c+(a+b-c)/(a+b)+4.0;
4. }
Space required to store variables: a, b, and c. Sp()= 3. S(P) = 3.
Example 2
Algorithm Sum(a[], n)
{
s:= 0.0;
for i = 1 to n do
s := s + a[i];
return s;
}
Example 2
Algorithm Sum(a[], n)
{
s:= 0.0;
for i = 1 to n do
s := s + a[i];
return s;
}
n = 1
a[ ] = n (for n elements)
i = 1
s = 1
Sp(n) = (n + 3).
Hence S(P) = (n + 3).
Contd..
•Time Complexity:
• T(P)=C+TP(I)
• The time, T(P), taken by a program, P, is the sum of its
compile time C and its run (or execution) time, TP(I).
• The compile time does not depend on the instance
characteristics.
• We will concentrate on estimating run time Tp(I).
Frequency count or Step count
Procedure:
• Comments, declaration steps are counted as zero number of steps.
• An assignment, return statement which does not involve any calls to
other functions counted as one step.
• Ignore lower order exponential when higher order exponential are
present.
• Ignore constants.
• For loops, such as the for, while, and repeat-until, we consider the
step counts only for the control part of the statement.
• The step count for each execution of the condition of a conditional
statements is one.
Example – Time complexity
Int sum (int a[], int n)
{
S=0;
For (i=1; i=n; i++)
S = S+a[i];
return S;
}
Example-1
Algorithm Sum(a[],n)
{
S = 0.0; 1
for i=1 to n do n +1
s = s+a[i]; n
return s; 1
}
2n + 3=O(n)
Example – Time complexity
Int sum (int a[], int n)
{
S=0;
For (i=o; i<n; i++)
S = S+a[i];
return S;
}
How to calculate  step count
S=0  count is 1
Second step  if n=3  (0<3, 1<3, 2<3, 3<3)  Total 4 step so count is n+1
Third step  body will execute only n time so count is n
Fourth step  count is 1
So Step count is  1+n+1+n+1 = 2n + 3
Example – Space complexity
Int sum (int a[], int n)
{
S=0;
For (i=o; i<n; i++)
S = S+a[i];
return S;
}
Example – Space complexity
Int sum (int a[], int n)
{
S=0;
For (i=o; i<n; i++)
S = S+a[i];
return S;
}
How to calculate  Space
a[]  n
n  1
S  1
i  1
So  n+3
void Add(int a[][], int b[][])
{
int c[][];
for i:=1 to m do
{
for j:=1 to n do
{
c[i,j]:=a[i,j]+b[i,j];
}
}
}
Example – Addition of two m×n matrices  Time complexity
void Add(int a[][], int b[][])
{
int c[][];
for i:=1 to m do
{
for j:=1 to n do
{
c[i,j]:=a[i,j]+b[i,j];
}
}
}
How to calculate  Time
First Condition will calculate n+1 time, and body of the first for loop is
n and again inner condition is n.
Second condition will calculate n+1 time so n(n+1). And body of the second
condition is n times, so n*n.
Now calculate : n+1 + n(n+1) + n*n = 2n2
+ 2n + 1
Example – Addition of two m×n matrices  Time complexity
Example – Addition of two m×n matrices  Space complexity
void Add(int a[][], int b[][])
{
int c[][];
for i:=1 to m do
{
for j:=1 to n do
{
c[i,j]:=a[i,j]+b[i,j];
}
}
}
Example – Addition of two m×n matrices  Space complexity
void Add(int a[][], int b[][])
{
int c[][];
for i:=1 to m do
{
for j:=1 to n do
{
c[i,j]:=a[i,j]+b[i,j];
}
}
}
a  n2
b  n2
c  n2
i  1, j  1, n  1 , m  1
Now calculate  3n2
+ 4
Find Time and Space
Time Complexity
Space Complexity
Example – Addition of two m×n matrices  Space complexity
void Add(int a[][], int b[][])
{
int c[][];
for i:=1 to m do
{
for j:=1 to n do
{
c[i,j]:=a[i,j]+b[i,j];
}
}
}
Procedure:
• Comments, declaration steps are
counted as zero number of steps.
• An assignment, return statement
which does not involve any calls to
other functions counted as one step.
• Ignore lower order exponential when
higher order exponential are present.
• Ignore constants.
• For loops, such as the for, while, and
repeat-until, we consider the step
counts only for the control part of
the statement.
• The step count for each execution of
the condition of a conditional
statements is one.
Example – Addition of two m×n matrices  Space complexity
void Add(int a[][], int b[][])
{
int c[][];
for i:=1 to m do
{
for j:=1 to n do
{
c[i,j]:=a[i,j]+b[i,j];
}
}
}
a  n2
b  n2
c  n2
i  1, j  1, n  1
Now calculate  3n2
+ 3
• Asymptotic efficiency means study of algorithms
efficiency for large inputs.
• To compare two algorithms with running times f(n)
and g(n), we need a rough measure that characterizes
how fast each function grows as n grows.
• Hint: use rate of growth
• Compare functions asymptotically!
(i.e., for large values of n)
Asymptotic efficiency
Asymptotic Notations
• Asymptotic Notations
are mainly used to
calculate the time
complexity of the
algorithm.
• 3 cases
• Big Oh Notation Big-Oh (O)
• Big Omega Notation Big-Omega (Ω)
• Big Theta Notation Big-Theta(Θ)
Asymptotic Notations- Big Oh(O)
• Big Oh(O) notation:
• Big-oh is the formal method of expressing the upper
bound of an algorithm's running time. It is the
measure of the Maximum amount of time. The
function f (n) = O (g (n)) [read as "f of n is big-oh of g
of n"] if and only if exist positive constant c and such
that
• It will find worst case of execution time
Definition:
• The function f (n) = O (g (n)) iff exist
positive constant c and n0.
Such that f(n)  c * g(n) for all n, n  n0
Definition
• Let f(n) and g(n) are two non negative functions, then f(n) = O g(n), if
there exist two positive constant C, n0.
• Such that f(n)  c * g(n) for all n, n  n0
• In other words, f(n) grows slower than or same rate as” g(n).
• f(n): This is the function that represents the actual complexity of the algorithm you are analyzing. It could
describe the number of operations, the amount of memory used, or some other measure of resource
consumption as a function of the input size n.
• g(n): This is a simpler or more general function used for comparison purposes. It is typically chosen to
represent a class of functions with similar growth rates.
• Examples
• f(n) = 3n+2 and g(n) = n, prove that f(n) = O g(n).
• Answer:
• You need to satisfy the condition f(n)  c * g(n) for all n, n  n0
• f(n)  c * g(n)  3n+2  c * n
• Examples
• f(n) = 3n+2 and g(n) = n, prove that f(n) = O g(n).
• Answer:
• You need to satisfy the condition f(n)  c * g(n) for all n, n  n0
• f(n)  c * g(n)  3n+2  c * n
• Substitute c = any positive value, let as assume 4
• 3n+2  4 * n
• Now substitute n  n0 as 1
• Let n0 =1 then 3n+2  4 * n  5  4  false
• Let n0 =2 then 3n+2  4 * n  8  8  true
• Let n0 =3 then 3n+2  4 * n  11  12  true
• Let n0 =4 then 3n+2  4 * n  14  16  ture
• So finally n0 >= 2
• 3n + 2 <= 4n, for all n >= 2, 3n + 2 =  (n)
Asymptotic Notations- Omega () notation
• Omega () notation :
• Omega () is the formal method of expressing the
lower bound of an algorithm's running time. It is the
measure of the minimum amount of time. The
function f (n) =  (g (n)) [read as "f of n is big-oh of g
of n"] if and only if exist positive constant c and such
that
• f(n)  c * g(n)
• It will find Best case of execution time
Definition
• Let f(n) and g(n) are two non negative functions, then f(n) =  g(n), if
there exist two positive constant C, n0.
• Such that f(n)  c * g(n) for all n, n  n0
• In other words,f(n) grows faster than or same rate as” g(n).
• Examples
• f(n) = 3n+2 and g(n) = n, prove that f(n) =  g(n).
• Answer:
• You need to satisfy the condition f(n)  c * g(n) for all n, n  n0
• f(n)  c * g(n)  3n+2  c * n
• Examples
• f(n) = 3n+2 and g(n) = n, prove that f(n) =  g(n).
• Answer:
• You need to satisfy the condition f(n)  c * g(n) for all n, n  n0
• f(n)  c * g(n)  3n+2  c * n
• Substitute c = any positive value, let as assume 1
• 3n+2  1 * n
• Now substitute n  n0 as 1
• Let n0 =1 then 3n+2  1 * n  5  1  true
• Let n0 =2 then 3n+2  1 * n  8  2  true
• Let n0 =3 then 3n+2  1 * n  11  3  true
• So finally, c = 1 & n0 >= 1
• 3n + 2  n, for all n >= 1, 3n + 2 =  (n)
Asymptotic Notations- Theta () notation
• Theta () notation :
• Theta () is the formal method of expressing the
Average bound of an algorithm's running time. It is
the measure of the average amount of time. The
function f (n) =  (g (n)) [read as "f of n is big-oh of g
of n"] if and only if exist positive constant c1 and c2
such that
• It will find Average case of execution time
Definition
• Let f(n) and g(n) are two non negative functions, then
f(n) =  g(n), if there exist two positive constant c1, c2,
and n0 .
• Such that c1g(n)  f(n)  c2g(n) for all n, n  n0.
• The definition states that the function f(n) lies
between c1 times the function g(n) and c2 times the
function g(n) except when n is smaller than n0.
• In other words,f(n) grows same rate as” g(n).
• Examples
• f(n) = 3n+2 and g(n) = n, prove that f(n) =  g(n).
• Answer:
• You need to satisfy the condition c1g(n)  f(n)  c2g(n) for all n, n  n0
• c1g(n)  f(n)  c2g(n)  c1g(n)  f(n)  c2g(n)
• Examples
• f(n) = 3n+2 and g(n) = n, prove that f(n) =  g(n).
• Answer:
• You need to satisfy the condition c1g(n)  f(n)  c2g(n) for all n, n  n0
• c1g(n)  f(n)  c2g(n)  c1g(n)  f(n)  c2g(n)
• Substitute c1 = 1 and c2 = 4.
• c1g(n)  f(n)  c2g(n)  1 * n  3n + 2  4 * n
• Now substitute n  n0 as 1, 2, 3 …
• Let n0 =1 then 1 * n  3n + 2  4 * n  1  5  4  false
• Let n0 =2 then 1 * n  3n + 2  4 * n  2  8  8  true
• Let n0 =3 then 1 * n  3n + 2  4 * n  3  1112  true
• So finally, c1 = 1, c2 = 4 & n0 >= 2
• 1 * n  3n + 2  4 * n, for all n >= 2, 3n + 2 =  (n)
Summary
• Big O Notation (O): Describes the upper bound of the time
complexity, representing the worst-case scenario.
• Big Omega Notation (Ω): Describes the lower bound, representing the
best-case scenario.
• Big Theta Notation (Θ): Describes the tight bound, representing both
the upper and lower bounds.
Example: Data Types in C
int age = 21; // Integer type
float height = 5.9; // Floating point
char grade = 'A'; // Character type
char name[] = "Kalpana"; // String
bool isPassed = true; // Boolean (C99)

Data Structures and Algorithms_Updated.pptx

  • 1.
  • 2.
    UNIT- 1 Introduction: • Programmingin C - Primitive data types, Structures, Self-referential structures, Pointers and structures, Dynamic memory allocation, Matrix multiplication; • Data Structure – Definition, Types, ADT, Operations; Mathematical notations - Big O, Omega and Theta, Complexity – Time, Space, Trade off.
  • 3.
    Data vs. Information Data:A value or a group of values is known as data. Example: CSE, SRM, 22-07-2023, Monday, Male, 7548844997, snagendraprabhu@gmail.com, Y, 99.50 Data is same as in its singular and plural forms Information: Processed data is known as Information (Data with meaning associated with it) Example: I am working in SRM Today is Monday My attendance percentage is 99.50 ‘Y’ is for Yes
  • 4.
    Data structure • DataType: the kind/type of data we are using is known as data type. Basic data types are: int, float, double, char, string Data structure: A data structure is basically a group of data elements that are put together under one name, and which defines a particular way of storing and organizing data in a computer so that it can be used efficiently. Data structures are widely applied in the following areas: Compiler design Operating system Statistical analysis package Data Base Management Systems (DBMS) Numerical analysis Simulation Artificial intelligence Graphics
  • 5.
    Introduction to DataStructures • A data structure is a way of storing data in a computer so that it can be used efficiently and it will allow the most efficient algorithm to be used. • A data structure should be seen as a logical concept that must address two fundamental • concerns. I. First, how the data will be stored, and II. Second, what operations will be performed on it.
  • 6.
    Types of DataStructure
  • 7.
  • 8.
    Primitive Data structure: •The primitive data structures are the basic data types that are available in most of the programming languages and can be manipulated directly by machine instructions. • The primitive data types are used to represent single values. • They are • Integer, • Float and Double , • Character , • String • Boolean
  • 9.
    Primitive Data structure: •Integer: This is used to represent a number without decimal point. • Eg: 12, 90 • Float and Double: This is used to represent a number with decimal point. • Eg: 45.1, 67.3 • Character : This is used to represent single character • Eg: ‘C’, ‘a’ • String: This is used to represent group of characters. • Eg: "College of Engineering" • Boolean: This is used represent logical values either true or false.
  • 10.
    Non-Primitive Data structure •The data structures that are derived from primary data types are known as non-Primitive data types. These data types are used to store group of values. • These once again can be classified as • Linear data structures • Non linear data structures
  • 11.
    Linear data structure •Linear data structure • A data structure is called linear if all of its elements are arranged in the linear order. In linear data structures, the elements are stored in non-hierarchical way where each element has the successors and predecessors except the first and last element. Linear order  each and every element will have attachment with first and last values. • Types of Linear Data Structures are given below: • Arrays • Linked List • Stack • Queue
  • 12.
    Non Linear datastructure • This data structure does not form a sequence i.e. each item or element is connected with two or more other items in a non-linear arrangement. The data elements are not arranged in sequential structure. • Types of Non Linear Data Structures are given below: • Trees • Graphs
  • 13.
  • 14.
    Why we needStructure ? • Arrays allow to define type of variables that can hold several data items of the same kind. Similarly structure is another user defined data type available in C that allows to combine data items of different kinds.
  • 15.
    Structures • Definition: Astructure is defined as a collection of data of same/different data types. All data items thus grouped are logically related and can be accessed using variables. Thus, structure can also be defined as a group of variables of same or different data types. The variables that are used to store the data are called members of the structure or fields of the structure. •In C, the structure is identified by the keyword struct.
  • 16.
    Structures- Example • Thestructure definition with tag name is called tagged structure. The tag name is the name of the structure. The syntax of tagged structure is shown below:
  • 17.
    Structures- Example • Ex:The structure definition to hold the student information such as name, roll_number and average_marks can be written as shown below:
  • 18.
    Structure declaration • “Howto declare a Variable in structure?” • As variables are declared before they are used in the function, the structures are also should be declared before they are used. A structure can be declared using different ways as shown below:
  • 19.
    Declaring structure variable •1st way: • Let's see the example to declare the structure variable by struct keyword. It should be declared within the main function. struct employee { int id; char name[50]; float salary; }; Now write given code inside the main() function. struct employee e1, e2; The variables e1 and e2 can be used to access the values stored in the structure.
  • 20.
    Declaring structure variable •2nd way: • Let's see another way to declare variable at the time of defining the structure. struct employee { int id; char name[50]; float salary; }e1,e2;
  • 21.
    Which approach isgood • If number of variables are not fixed, use the 1st approach. It provides you the flexibility to declare the structure variable many times. • If no. of variables are fixed, use 2nd approach. It saves your code to declare a variable in main() function.
  • 22.
    Example- Create structvariables • Suppose you want to keep track of your books in a library. You might want to track the following attributes about each book − • Title • Author • Subject • Book ID
  • 23.
    Example- Create structvariables struct Books { char title[50]; char author[50]; char subject[100]; int book_id; } b1;
  • 24.
    #include <stdio.h> struct student { charname[40]; // Student name int roll; // Student enrollment float CPI; // Student mobile number int backlog; }; int main() { struct student student1; // Simple structure variable // Input data in structure members using dot operator printf("Enter Student Name:"); scanf("%s", student1.name); printf("Enter Student Roll Number:"); scanf("%d", &student1.roll); printf("Enter Student CPI:"); scanf("%f", &student1.CPI); printf("Enter Student Backlog:"); scanf("%d", &student1.backlog); // Display data in structure members using dot operator printf("nStudent using simple structure variable. n"); printf("Student name: %sn", student1.name); printf("Student Enrollment: %dn", student1.roll); printf("Student CPI: %fn", student1.CPI); printf("Student Backlog: %in", student1.backlog); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Enter Student Name:aaa Enter Student Roll Number:111 Enter Student CPI:7.89 Enter Student Backlog:0 Student using simple structure variable. Student name: aaa Student Enrollment: 111 Student CPI: 7.890000 Student Backlog: 0 Program Output Write a program to read and display student information using structure.
  • 25.
    Nested Structure inC • A structure inside another structure is called nested structure. • C provides us the feature of nesting one structure within another structure. • For example, • we may need to store the address of an entity employee in a structure. The attribute address may also have the subparts as street number, city, state, and pin code. Hence, to store the address of the employee, we need to store the address of the employee into a separate structure and nest the structure address into the structure employee.
  • 26.
    The structure canbe nested in the following ways. • By separate structure • By Embedded structure
  • 27.
    Separate structure • Here,we create two structures, but the dependent structure should be used inside the main structure as a member. Consider the following example. struct Date { int dd; int mm; int yyyy; }; struct Employee { int id; char name[20]; struct Date doj; }emp1; As you can see, doj (date of joining) is the variable of type Date. Here doj is used as a member in Employee structure.
  • 28.
    Embedded structure • Theembedded structure enables us to declare the structure inside the structure. Hence, it requires less line of codes but it can not be used in multiple data structures. Consider the following example. struct Employee { int id; char name[20]; struct Date { int dd; int mm; int yyyy; }doj; }emp1;
  • 29.
    Accessing Nested Structure •We can access the member of the nested structure by Outer_Structure.Nested_Structure.member as given below: emp1.doj.dd emp1.doj.mm emp1.doj.yyyy
  • 30.
    Example for nestedstructure #include<stdio.h> struct address { char city[20]; int pin; char phone[14]; }; struct employee { char name[20]; struct address add; }; void main () { struct employee emp; printf("Enter employee information?n"); scanf("%s %s %d %s",emp.name,emp.add.city, &emp.add.pin, emp.add.phone); printf("Printing the employee information....n"); printf("name: %snCity: %snPincode: %dnPhone: %s",emp.name,emp.add.city,emp.add.pin,emp.add.phone); }
  • 31.
    Array of Structures •Why use an array of structures? • Consider a case, where we need to store the data of 5 students, we can easily create 5 variable and do it. • However, the complexity of the program will be increased if there are 20 students. In that case, we will have to declare 20 different structure variables and store them one by one. This will always be tough since we will have to declare a variable every time we add a student. • Array of Structures in C • An array of structres in C can be defined as the collection of multiple structures variables where each variable contains information about different entities. The array of structures in C are used to store information about multiple entities of different data types. The array of structures is also known as the collection of structures.
  • 32.
    Array of Structuresin C #include<stdio.h> #include <string.h> struct student{ int rollno; char name[10]; }; int main(){ int i; struct student st[5]; printf("Enter Records of 5 students"); for(i=0;i<5;i++){ printf("nEnter Rollno:"); scanf("%d",&st[i].rollno); printf("nEnter Name:"); scanf("%s",&st[i].name); } printf("nStudent Information List:"); for(i=0;i<5;i++){ printf("nRollno:%d, Name:%s",st[i].rollno,st[i].name); } return 0; }
  • 33.
    Why do werequire a Self-referential structure? • Self-referential structure plays a vital role in the linked list, trees, graphs, and many more data structures. • By using the structure, we can easily implement these data structures efficiently. • For defining a particular node, the structure plays a very important role. • In a linked list, the structure is used to store the data information and the address of the next node in the given linked list. • Mainly the data part is of integer type, and the link address part is of pointer type, which holds the address of the next node, so that it can for the Link ultimately.
  • 34.
    Pointers • The pointerin C language is a variable which stores the address of another variable. This variable can be of type int, char, array, function, or any other pointer. • Consider the following example to define a pointer which stores the address of an integer. • int n = 10; • int *p = &n; • // Variable p of type pointer is pointing to the addres s of the variable n of type integer.
  • 35.
    Declaring a pointer •The pointer in c language can be declared using * (asterisk symbol). • Syntax of Pointer • Datatype *Variable_name • int *a;//pointer to int • char *c;//pointer to char
  • 36.
    Initialization of CPointer variable • Pointer Initialization is the process of assigning address of a variable to a pointer variable. It contains the address of a variable of the same data type. • int a = 10; • int *ptr; //pointer declaration • ptr = &a; //pointer initialization
  • 37.
    Simple pointer example #include<stdio.h> intmain(){ int number=50; int *p; p=&number; //stores the address of number variable printf("Address of p variable is %x n",p); // p contains the address of the number printf("Value of p variable is %d n",*p); // As we know that * is used to dereference a pointer therefore if we print *p, we will get the value stored at the address contained by p. return 0; }
  • 38.
    Simple pointer example •#include <stdio.h> • int main () { • int var = 20; /* actual variable declaration */ • int *ip; /* pointer variable declaration */ • ip = &var; /* store address of var in pointer variable*/ • printf("Address of var variable: %xn", &var ); • /* address stored in pointer variable */ • printf("Address stored in ip variable: %xn", ip ); • /* access the value using the pointer */ • printf("Value of *ip variable: %dn", *ip ); • return 0; • }
  • 39.
    Structure Pointer • Thestructure pointer points to the address of a memory block where the Structure is being stored. Like a pointer that tells the address of another variable of any data type (int, char, float) in memory. And here, we use a structure pointer which tells the address of a structure in memory by pointing pointer variable ptr to the structure variable. • Declare a Structure Pointer • The declaration of a structure pointer is similar to the declaration of the structure variable. • So, we can declare the structure pointer and variable inside and outside of the main() function. To declare a pointer variable in C, we use the asterisk (*) symbol before the variable's name. •struct structure_name *ptr;
  • 40.
    Pointer to structure structst { int i; float f; }v1; struct st *p = &v1;
  • 41.
    Structure using pointersProgram #include <stdio.h> int main() { struct book { char name[25]; char author[25]; int callno; }; struct book b1 = { "Let us C", "ABC", 101 }; struct book *ptr; ptr = &b1; printf("Address of b1: %pn", &b1); return 0; }
  • 42.
    Structure using pointersProgram #include <stdio.h> int main() { struct book { char name[25]; char author[25]; int callno; }; struct book b1 = { "Let us C", "ABC", 101 }; struct book *ptr; ptr = &b1; printf("%s %s %dn", b1.name, b1.author, b1.callno); printf("%s %s %dn", ptr->name, ptr->author, ptr->callno); printf("%p %p %pn", &ptr->name,&ptr->author,&ptr->callno); return 0; }
  • 43.
    Dynamic memory allocationin C • The concept of dynamic memory allocation in c language enables the C programmer to allocate memory at runtime. • Dynamic memory allocation in c language is possible by 4 functions of stdlib.h header file. • malloc() • calloc() • realloc() • free()
  • 44.
    Before learning abovefunctions, let's understand the difference between static memory allocation and dynamic memory allocation. static memory allocation dynamic memory allocation memory is allocated at compile time. memory is allocated at run time. memory can't be increased while executing program. memory can be increased while executing program. used in array. used in linked list.
  • 45.
    Methods used fordynamic memory allocation. malloc() memory allocation allocates single block of requested memory. calloc() Contiguous Allocation allocates multiple block of requested memory. realloc() reallocation reallocates the memory occupied by malloc() or calloc() functions. free() frees the dynamically allocated memory.
  • 46.
    malloc() method • The“malloc” or “memory allocation” method in C is used to dynamically allocate a single large block of memory with the specified size. • 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)
  • 47.
    Example for syntax •ptr = (int*) malloc (100 * sizeof(int)); • Since the size of int is 4 bytes, this statement will allocate 400 bytes of memory. And, the pointer ptr holds the address of the first byte in the allocated memory.
  • 48.
    calloc() method • “calloc”or “contiguous allocation” method in C is used to dynamically allocate the specified number of blocks of memory of the specified type. it is very much similar to malloc() but has two different points and these are: • It initializes each block with a default value ‘0’. • It has two parameters or arguments as compare to malloc(). • The syntax of calloc() function is given below: • ptr=(cast-type*)calloc(number, byte-size)
  • 49.
    Example for syntax •ptr = (float*) calloc(25, sizeof(float)); • This statement allocates contiguous space in memory for 25 elements each with the size of the float.
  • 50.
    realloc() method • Ifmemory 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)
  • 51.
    free() function inC • 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)
  • 52.
    Sample program –Memory Allocation #include<stdio.h> #include<stdlib.h> int main(){ int n,i,*ptr,sum=0; printf("Enter number of elements: "); scanf("%d",&n); ptr=(int*)malloc(n*sizeof(int)); //memory allocated using malloc if(ptr==NULL) { printf("Sorry! unable to allocate memory"); exit(0); } printf("Enter elements of array: "); for(i=0;i<n;++i) { scanf("%d",ptr+i); sum+=*(ptr+i); } printf("Sum=%d",sum); free(ptr); return 0; }
  • 53.
    Matrix Multiplication • Inmatrix multiplication, it is not necessary that both matrices must be a square matrix, as in addition and subtraction. • Suppose we have a matrix A of m×n dimensions and a matrix B of n×k dimensions, then the resultant matrix will be of m×k dimensions.
  • 54.
  • 55.
  • 56.
    #include<stdio.h> #include<stdlib.h> int main(){ int a[10][10],b[10][10],mul[10][10],r,c,i,j,k; system("cls"); printf("enterthe number of row="); scanf("%d",&r); printf("enter the number of column="); scanf("%d",&c); printf("enter the first matrix element=n"); for(i=0;i<r;i++) { for(j=0;j<c;j++) { scanf("%d",&a[i][j]); } } printf("enter the second matrix element=n"); for(i=0;i<r;i++) { for(j=0;j<c;j++) { scanf("%d",&b[i][j]); } } printf("multiply of the matrix=n"); for(i=0;i<r;i++) { for(j=0;j<c;j++) { mul[i][j]=0; for(k=0;k<c;k++) { mul[i][j]+=a[i][k]*b[k][j]; } } } //for printing result for(i=0;i<r;i++) { for(j=0;j<c;j++) { printf("%dt",mul[i][j]); } printf("n"); } return 0; }
  • 57.
    • Output enter thenumber of row=3 enter the number of column=3 enter the first matrix element= 1 1 1 2 2 2 3 3 3 enter the second matrix element= 1 1 1 2 2 2 3 3 3 multiply of the matrix= 6 6 6 12 12 12 18 18 18
  • 58.
    Classification of DataStructures • Data structures can be classified as i. Simple data structure ii. Compound data structure i. Linear data structure ii. Non linear data structure 5 8
  • 59.
  • 60.
    Operations on datastructures 1. Inserting: adding new data items to the given list of data items. 2. Deleting: remove (delete) a particular data item from the given collection of data items. 3. Searching: find the location of one or more data items that satisfy the given constraint. Such a data item may or may not be present in the given collection of data items. 4. Sorting: arranging data elements in specific order like ascending order or descending order depending on the type of application. 5. Merging: two lists of sorted data items can be combined to form a single list of sorted data items Traverse Etc.,
  • 61.
  • 62.
    Data Structure Operations •Linked List - Definition and Declaration (Structure) - Creation (Head node) - Insertion - Deletion - Search / Traverse - Types (Single, Double, Circular) - Applications
  • 63.
    Data Structure Operations •Stack - Definition and Declaration (Array / List) - Insertion (Push) - Deletion (Pop) - Searching - Applications
  • 64.
    Data Structure Operations •Queue - Definition and Declaration (Array / List) - Insertion ( Enqueue ) - Deletion ( Dequeue) - Types ( Linear, Circular ) - Applications
  • 65.
    Data Structure Operations •Tree - Definition and Declaration (Array / List) - Insertion - Deletion - Types ( Binary Tree, Binary Search Tree, AVL Tree, Etc..) - Applications
  • 66.
    Abstract Data Type •An abstract data type is an abstraction of a data structure that provides only the interface to which the data structure must adhere. The interface does not give any specific details about something should be implemented or in what programming language. • In other words, we can say that abstract data types are the entities that are definitions of data and operations but do not have implementation details. In this case, we know the data that we are storing and the operations that can be performed on the data, but we don't know about the implementation details.
  • 67.
    Let's understand theabstract data type with a real-world example. • If we consider the smartphone. We look at the high specifications of the smartphone, such as: • RAM Size • Processor • inch LCD screen • Dual camera • Android Version • The above specifications of the smartphone are the abstract data, and we can also perform the following operations on the smartphone: • call(): We can call through the smartphone. • text(): We can text a message. • photo(): We can click a photo. • video(): We can also make a video. • The smartphone is an entity whose data or specifications and operations are given above. The abstract/logical view and operations are the abstract or logical views of a smartphone.
  • 68.
    Let us seesome operations of ADT in Data structure • Stack − • isFull(), This is used to check whether stack is full or not • isEmpty(), This is used to check whether stack is empty or not • push(x), This is used to push x into the stack • pop(), This is used to delete one element from top of the stack • peek(), This is used to get the top most element of the stack • size(), this function is used to get number of elements present into the stack • Queue − • isFull(), This is used to check whether queue is full or not • isEmpty(), This is used to check whether queue is empty or not • Enqueue(x), This is used to add x into the queue at the rear end • Dequeue(), This is used to delete one element from the front end of the queue • size(), this function is used to get number of elements present into the queue
  • 69.
    Algorithm Analysis • Thealgorithm can be analyzed in two levels, i.e., first is before creating the algorithm, and second is after creating the algorithm. The following are the two analysis of an algorithm: • Priori Analysis: Here, priori analysis is the theoretical analysis of an algorithm which is done before implementing the algorithm. Various factors can be considered before implementing the algorithm like processor speed, which has no effect on the implementation part. • Posterior Analysis: Here, posterior analysis is a practical analysis of an algorithm. The practical analysis is achieved by implementing the algorithm using any programming language. This analysis basically evaluate that how much running time and space taken by the algorithm.
  • 70.
    70 Algorithm Analysis andComplexity • The performances of algorithms can be measured on the scales of Time and Space. • The Time Complexity of an algorithm or a program is a function of the running time of the algorithm or a program. • The Space Complexity of an algorithm or a program is a function of the space needed by the algorithm or program to run to completion.
  • 71.
    The Need forAnalysis • Algorithms are often quite different from one another, though the objective of these algorithms are the same. • For example, we know that a set of numbers can be sorted using different algorithms. • Number of comparisons performed by one algorithm may vary with others for the same input. • Hence, time complexity of those algorithms may differ. • At the same time, we need to calculate the memory space required by each algorithm.
  • 72.
    The Need forAnalysis • Analysis of algorithm is the process of analyzing the problem-solving capability of the algorithm in terms of the time and size required (the size of memory for storage while implementation). • However, the main concern of analysis of algorithms is the required time or performance. Generally, we perform the following types of analysis − • Worst-case − The maximum number of steps taken on any instance of size a. • Best-case − The minimum number of steps taken on any instance of size a. • Average case − An average number of steps taken on any instance of size a.
  • 73.
    Algorithm Complexity • Theperformance of the algorithm can be measured in two factors: • Time complexity • Space complexity • Time complexity: The time complexity of an algorithm is the amount of time required to complete the execution. The time complexity of an algorithm is denoted by the big O notation. Here, big O notation is the asymptotic notation to represent the time complexity. The time complexity is mainly calculated by counting the number of steps to finish the execution. Let's understand the time complexity through an example.
  • 74.
    Algorithm Complexity • Timecomplexity: sum=0; // Suppose we have to calculate the sum of n numbers. for i=1 to n sum=sum+i; // when the loop ends then sum holds the sum of the n nu mbers return sum; • In the above code, the time complexity of the loop statement will be atleast n, and if the value of n increases, then the time complexity also increases.
  • 75.
    Algorithm Complexity • Spacecomplexity: An algorithm's space complexity is the amount of space required to solve a problem and produce an output. Similar to the time complexity, space complexity is also expressed in big O notation. • For an algorithm, the space is required for the following purposes: 1. To store program instructions 2. To store constant values 3. To store variable values 4. To track the function calls, jumping statements, etc. • Auxiliary space: The extra space required by the algorithm, excluding the input size, is known as an auxiliary space. The space complexity considers both the spaces, i.e., auxiliary space, and space used by the input. So, • Space complexity = Auxiliary space + Input size.
  • 76.
    Performance Analysis • Thereare many things upon which the performance will depend. • Does the program efficiently use primary and Secondary storage? • Is the program's running Time acceptable for the task? • Does it do what we want it to do? • Does it work correctly according to the specifications of the task? • Does the program contain documentation that shows how to use it and how it works? • Is the program's code readable?
  • 77.
    Performance Analysis •Time complexityand Space complexity • We will find best case, worst case and Average case • For Time complexity we will use two method • Frequency count or step count • Asymptotic notation • For Space complexity we will use method called • Frequency count or step count
  • 78.
    Space Complexity • Thespace needed by a program has the following components. • Instruction space • Data Space • Environmental stack space
  • 79.
    • Instruction space •Instruction space is the space needed to store the compiled version of the program instructions. • Data space • Data space is the space needed to store all constant and variable values. Data space has two components. • Space needed by constants( ex; 1 and 2 in max of n num algorithm) and simple variables( such as i, j, n etc). • Environmental stack space • The environment stack is used to save information needed to resume execution of partially completed functions. • Each time a function is invoked the following data are saved on the environment stack.
  • 80.
    Contd.. Therefore, We candivide the total space needed by a program into two parts: i) Fixed Space Requirements (C) Independent of the characteristics of the problem instance ( I ) • Instruction space • Data space for simple variables and constants. ii) Variable Space Requirements (SP(I)) depend on the characteristics of the problem instance ( I ) • Number of inputs and outputs associated with I • recursive stack space ( formal parameters, local variables, return address ). • Therefore, the space requirement of any problem P can be written as S(p)=C +Sp( Instance characteristics )
  • 81.
    • Note: • Whenanalyzing the space complexity of an algorithm, we concentrate only on estimating Sp (Instance characteristics ). • We do not concentrate on estimating fixed part c .
  • 82.
    Example-1 1. Algorithm abc(a, b, c) 2. { 3. return a+b+b*c+(a+b-c)/(a+b)+4.0; 4. } Space required to store variables: a, b, and c. Sp()= 3. S(P) = 3.
  • 83.
    Example 2 Algorithm Sum(a[],n) { s:= 0.0; for i = 1 to n do s := s + a[i]; return s; }
  • 84.
    Example 2 Algorithm Sum(a[],n) { s:= 0.0; for i = 1 to n do s := s + a[i]; return s; } n = 1 a[ ] = n (for n elements) i = 1 s = 1 Sp(n) = (n + 3). Hence S(P) = (n + 3).
  • 85.
    Contd.. •Time Complexity: • T(P)=C+TP(I) •The time, T(P), taken by a program, P, is the sum of its compile time C and its run (or execution) time, TP(I). • The compile time does not depend on the instance characteristics. • We will concentrate on estimating run time Tp(I).
  • 86.
    Frequency count orStep count Procedure: • Comments, declaration steps are counted as zero number of steps. • An assignment, return statement which does not involve any calls to other functions counted as one step. • Ignore lower order exponential when higher order exponential are present. • Ignore constants. • For loops, such as the for, while, and repeat-until, we consider the step counts only for the control part of the statement. • The step count for each execution of the condition of a conditional statements is one.
  • 87.
    Example – Timecomplexity Int sum (int a[], int n) { S=0; For (i=1; i=n; i++) S = S+a[i]; return S; }
  • 88.
    Example-1 Algorithm Sum(a[],n) { S =0.0; 1 for i=1 to n do n +1 s = s+a[i]; n return s; 1 } 2n + 3=O(n)
  • 89.
    Example – Timecomplexity Int sum (int a[], int n) { S=0; For (i=o; i<n; i++) S = S+a[i]; return S; } How to calculate  step count S=0  count is 1 Second step  if n=3  (0<3, 1<3, 2<3, 3<3)  Total 4 step so count is n+1 Third step  body will execute only n time so count is n Fourth step  count is 1 So Step count is  1+n+1+n+1 = 2n + 3
  • 90.
    Example – Spacecomplexity Int sum (int a[], int n) { S=0; For (i=o; i<n; i++) S = S+a[i]; return S; }
  • 91.
    Example – Spacecomplexity Int sum (int a[], int n) { S=0; For (i=o; i<n; i++) S = S+a[i]; return S; } How to calculate  Space a[]  n n  1 S  1 i  1 So  n+3
  • 92.
    void Add(int a[][],int b[][]) { int c[][]; for i:=1 to m do { for j:=1 to n do { c[i,j]:=a[i,j]+b[i,j]; } } } Example – Addition of two m×n matrices  Time complexity
  • 93.
    void Add(int a[][],int b[][]) { int c[][]; for i:=1 to m do { for j:=1 to n do { c[i,j]:=a[i,j]+b[i,j]; } } } How to calculate  Time First Condition will calculate n+1 time, and body of the first for loop is n and again inner condition is n. Second condition will calculate n+1 time so n(n+1). And body of the second condition is n times, so n*n. Now calculate : n+1 + n(n+1) + n*n = 2n2 + 2n + 1 Example – Addition of two m×n matrices  Time complexity
  • 94.
    Example – Additionof two m×n matrices  Space complexity void Add(int a[][], int b[][]) { int c[][]; for i:=1 to m do { for j:=1 to n do { c[i,j]:=a[i,j]+b[i,j]; } } }
  • 95.
    Example – Additionof two m×n matrices  Space complexity void Add(int a[][], int b[][]) { int c[][]; for i:=1 to m do { for j:=1 to n do { c[i,j]:=a[i,j]+b[i,j]; } } } a  n2 b  n2 c  n2 i  1, j  1, n  1 , m  1 Now calculate  3n2 + 4
  • 96.
  • 97.
  • 98.
  • 99.
    Example – Additionof two m×n matrices  Space complexity void Add(int a[][], int b[][]) { int c[][]; for i:=1 to m do { for j:=1 to n do { c[i,j]:=a[i,j]+b[i,j]; } } } Procedure: • Comments, declaration steps are counted as zero number of steps. • An assignment, return statement which does not involve any calls to other functions counted as one step. • Ignore lower order exponential when higher order exponential are present. • Ignore constants. • For loops, such as the for, while, and repeat-until, we consider the step counts only for the control part of the statement. • The step count for each execution of the condition of a conditional statements is one.
  • 100.
    Example – Additionof two m×n matrices  Space complexity void Add(int a[][], int b[][]) { int c[][]; for i:=1 to m do { for j:=1 to n do { c[i,j]:=a[i,j]+b[i,j]; } } } a  n2 b  n2 c  n2 i  1, j  1, n  1 Now calculate  3n2 + 3
  • 101.
    • Asymptotic efficiencymeans study of algorithms efficiency for large inputs. • To compare two algorithms with running times f(n) and g(n), we need a rough measure that characterizes how fast each function grows as n grows. • Hint: use rate of growth • Compare functions asymptotically! (i.e., for large values of n) Asymptotic efficiency
  • 102.
    Asymptotic Notations • AsymptoticNotations are mainly used to calculate the time complexity of the algorithm. • 3 cases • Big Oh Notation Big-Oh (O) • Big Omega Notation Big-Omega (Ω) • Big Theta Notation Big-Theta(Θ)
  • 103.
    Asymptotic Notations- BigOh(O) • Big Oh(O) notation: • Big-oh is the formal method of expressing the upper bound of an algorithm's running time. It is the measure of the Maximum amount of time. The function f (n) = O (g (n)) [read as "f of n is big-oh of g of n"] if and only if exist positive constant c and such that • It will find worst case of execution time Definition: • The function f (n) = O (g (n)) iff exist positive constant c and n0. Such that f(n)  c * g(n) for all n, n  n0
  • 104.
    Definition • Let f(n)and g(n) are two non negative functions, then f(n) = O g(n), if there exist two positive constant C, n0. • Such that f(n)  c * g(n) for all n, n  n0 • In other words, f(n) grows slower than or same rate as” g(n). • f(n): This is the function that represents the actual complexity of the algorithm you are analyzing. It could describe the number of operations, the amount of memory used, or some other measure of resource consumption as a function of the input size n. • g(n): This is a simpler or more general function used for comparison purposes. It is typically chosen to represent a class of functions with similar growth rates.
  • 105.
    • Examples • f(n)= 3n+2 and g(n) = n, prove that f(n) = O g(n). • Answer: • You need to satisfy the condition f(n)  c * g(n) for all n, n  n0 • f(n)  c * g(n)  3n+2  c * n
  • 106.
    • Examples • f(n)= 3n+2 and g(n) = n, prove that f(n) = O g(n). • Answer: • You need to satisfy the condition f(n)  c * g(n) for all n, n  n0 • f(n)  c * g(n)  3n+2  c * n • Substitute c = any positive value, let as assume 4 • 3n+2  4 * n • Now substitute n  n0 as 1 • Let n0 =1 then 3n+2  4 * n  5  4  false • Let n0 =2 then 3n+2  4 * n  8  8  true • Let n0 =3 then 3n+2  4 * n  11  12  true • Let n0 =4 then 3n+2  4 * n  14  16  ture • So finally n0 >= 2 • 3n + 2 <= 4n, for all n >= 2, 3n + 2 =  (n)
  • 107.
    Asymptotic Notations- Omega() notation • Omega () notation : • Omega () is the formal method of expressing the lower bound of an algorithm's running time. It is the measure of the minimum amount of time. The function f (n) =  (g (n)) [read as "f of n is big-oh of g of n"] if and only if exist positive constant c and such that • f(n)  c * g(n) • It will find Best case of execution time
  • 108.
    Definition • Let f(n)and g(n) are two non negative functions, then f(n) =  g(n), if there exist two positive constant C, n0. • Such that f(n)  c * g(n) for all n, n  n0 • In other words,f(n) grows faster than or same rate as” g(n).
  • 109.
    • Examples • f(n)= 3n+2 and g(n) = n, prove that f(n) =  g(n). • Answer: • You need to satisfy the condition f(n)  c * g(n) for all n, n  n0 • f(n)  c * g(n)  3n+2  c * n
  • 110.
    • Examples • f(n)= 3n+2 and g(n) = n, prove that f(n) =  g(n). • Answer: • You need to satisfy the condition f(n)  c * g(n) for all n, n  n0 • f(n)  c * g(n)  3n+2  c * n • Substitute c = any positive value, let as assume 1 • 3n+2  1 * n • Now substitute n  n0 as 1 • Let n0 =1 then 3n+2  1 * n  5  1  true • Let n0 =2 then 3n+2  1 * n  8  2  true • Let n0 =3 then 3n+2  1 * n  11  3  true • So finally, c = 1 & n0 >= 1 • 3n + 2  n, for all n >= 1, 3n + 2 =  (n)
  • 111.
    Asymptotic Notations- Theta() notation • Theta () notation : • Theta () is the formal method of expressing the Average bound of an algorithm's running time. It is the measure of the average amount of time. The function f (n) =  (g (n)) [read as "f of n is big-oh of g of n"] if and only if exist positive constant c1 and c2 such that • It will find Average case of execution time
  • 112.
    Definition • Let f(n)and g(n) are two non negative functions, then f(n) =  g(n), if there exist two positive constant c1, c2, and n0 . • Such that c1g(n)  f(n)  c2g(n) for all n, n  n0. • The definition states that the function f(n) lies between c1 times the function g(n) and c2 times the function g(n) except when n is smaller than n0. • In other words,f(n) grows same rate as” g(n).
  • 113.
    • Examples • f(n)= 3n+2 and g(n) = n, prove that f(n) =  g(n). • Answer: • You need to satisfy the condition c1g(n)  f(n)  c2g(n) for all n, n  n0 • c1g(n)  f(n)  c2g(n)  c1g(n)  f(n)  c2g(n)
  • 114.
    • Examples • f(n)= 3n+2 and g(n) = n, prove that f(n) =  g(n). • Answer: • You need to satisfy the condition c1g(n)  f(n)  c2g(n) for all n, n  n0 • c1g(n)  f(n)  c2g(n)  c1g(n)  f(n)  c2g(n) • Substitute c1 = 1 and c2 = 4. • c1g(n)  f(n)  c2g(n)  1 * n  3n + 2  4 * n • Now substitute n  n0 as 1, 2, 3 … • Let n0 =1 then 1 * n  3n + 2  4 * n  1  5  4  false • Let n0 =2 then 1 * n  3n + 2  4 * n  2  8  8  true • Let n0 =3 then 1 * n  3n + 2  4 * n  3  1112  true • So finally, c1 = 1, c2 = 4 & n0 >= 2 • 1 * n  3n + 2  4 * n, for all n >= 2, 3n + 2 =  (n)
  • 115.
    Summary • Big ONotation (O): Describes the upper bound of the time complexity, representing the worst-case scenario. • Big Omega Notation (Ω): Describes the lower bound, representing the best-case scenario. • Big Theta Notation (Θ): Describes the tight bound, representing both the upper and lower bounds.
  • 121.
    Example: Data Typesin C int age = 21; // Integer type float height = 5.9; // Floating point char grade = 'A'; // Character type char name[] = "Kalpana"; // String bool isPassed = true; // Boolean (C99)