0% found this document useful (0 votes)
27 views57 pages

1DSA

The document provides an overview of data structures and arrays. It defines data structures as a way to store and organize data for efficient access and updating. Primitive data structures like integers and characters store single values directly, while non-primitive structures like arrays and linked lists are more complex. Linear structures like arrays, linked lists, stacks and queues arrange elements sequentially; non-linear structures like trees and graphs have multiple connections. The document also describes common operations on data structures and provides details on declaring, initializing, and accessing values in one-dimensional arrays.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
27 views57 pages

1DSA

The document provides an overview of data structures and arrays. It defines data structures as a way to store and organize data for efficient access and updating. Primitive data structures like integers and characters store single values directly, while non-primitive structures like arrays and linked lists are more complex. Linear structures like arrays, linked lists, stacks and queues arrange elements sequentially; non-linear structures like trees and graphs have multiple connections. The document also describes common operations on data structures and provides details on declaring, initializing, and accessing values in one-dimensional arrays.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 57

Page 1

UNIT - 1: INTRODUCTION

Syllabus: Data Structures, Classifications (Primitive & Non-Primitive), Data


structure Operations, Review of Arrays, Structures, Self-Referential Structures,
and Unions. Pointers and Dynamic Memory Allocation Functions.
Representation of Linear Arrays in Memory, dynamically allocated arrays.
Performance analysis of an algorithm and space and time complexities.

by - Hari Krishna
Page 2

Data Structures:

A data structure is a storage that is used to store and organize data. It is a


way of arranging data on a computer so that it can be accessed and updated
efficiently.
A data structure is not only used for organizing the data. It is also used for
processing, retrieving, and storing data.
The data structure is not any programming language like C, C++, java, etc.
It is a set of algorithms that we can use in any programming language to
structure the data in the memory.

Classifications:

Non

by - Hari Krishna
Page 3

Primitive Data Structures:

Primitive data structure is a fundamental type of data structure that stores


the data of only one type. It is a data structure that can hold a single value in a
specific location.

These data structures can be manipulated or operated directly by machine-level


instructions.

Integer(2 bytes) - The integer data type contains the numeric values. It
contains the whole numbers that can be either negative or positive.
Ex: 10, 97, -41
Float(4 bytes) - The float is a data type that can hold decimal values upto
6 digits.
Ex: 3.127461
Character(1 byte) - It is a data type that can hold a single character value
both uppercase and lowercase such as 'A' or 'a'.
Boolean(1 byte) - It is a data type that can hold either a True or a False
value.
Ex: 1 or 0 (True or False).

Non-primitive Data Structures:

Non-primitive data structures are complex data structures that are derived
from primitive data structures. It can hold multiple values either in a contiguous
location or random locations.

The non-primitive data types are defined by the programmer. The non-primitive
data structure is further classified into two categories.

by - Hari Krishna
Page 4

Linear Data Structures


Non-Linear Data Structures

Linear Data Structures:

Linear Data Structure consists of data elements arranged in a sequential


manner where every element is connected to its previous and next elements.

The following are the types of linear data structure

Array: An array is a collection of similar data elements. These data


elements have the same data type. The elements of the array are stores in
consecutive memory locations and are referenced by an index.

Syntax: data_type array_name[size];

Example: int marks[10];

Memory representation of an array of 10 elements

Linked List: A linked list is a linear data structures that is used to maintain
a list-like structure in the computer memory. It is a group of nodes that are
not stored at contiguous locations. Each node of the list is linked to its
adjacent node with the help of pointers.

Simple Linked List

by - Hari Krishna
Page 5

Stack: Stack is a linear data structure that follows a particular order in


which the operations are performed. The order is LIFO(Last in first out).
Entering and retrieving data is possible from only one end.

It contains two operations – push, pop

Stack

Queue: Queue is a linear data structure in which elements can be inserted


from only one end which is known as rear and deleted from another end
known as front. It follows the FIFO(First In First Out) order.

It contains two operations – enqueue, dequeue

Queue

by - Hari Krishna
Page 6

Non-Linear Data Structures:

Non-linear Data Structures do not have any set sequence of connecting all
its elements and every element can have multiple paths to attach to other
elements.

The following are the types of linear data structure:

Trees: A tree is a multilevel data structure defined as a set of nodes. The


topmost node is named root node while the bottom most nodes are called
leaf nodes. Each node has only one parent but can have multiple children.

Trees

Graph: A graph is a pictorial representation of a set of objects connected


by links known as edges. The interconnected nodes are represented by
points named vertices, and the links that connect the vertices are called
edges.

Graph

by - Hari Krishna
Page 7

Data Structures Operations:

The common operations that can be performed on the data structures are as
follows

Traversing: Traversing a Data Structure means to visit the element stored


in it. It visits data in a systematic manner.
Searching: Searching means to find a particular element in the given
data-structure. It is considered as successful when the required element is
found.
Sorting: Sorting means to arrange the data elements in either Ascending
or Descending order.
Create: Create is an operation used to reserve memory for the data
elements of the program. We can perform this operation using a declaration
statement. The creation of data structure can take place either during the
following:
1. Compile-time
2. Run-time
Insertion: Insertion means inserting or adding new data elements to the
collection. The operation of insertion is successful when the required
element is added to the required data-structure.
Deletion: Deletion means to remove or delete a specific data element from
the given list of data elements. The operation of deletion is successful
when the required element is deleted from the data structure.
Merge: Merge means to combine data elements of two sorted lists in order
to form a single list of sorted data elements.
Splitting: The Splitting operation allows us to divide data into various
subparts decreasing the overall process completion time.

by - Hari Krishna
Page 8

Arrays:

An array is a collection of similar data elements. These data elements


have the same data type. The elements of the array are stores in consecutive
memory locations and are referenced by an index.

Storing Values in array:

When we declare an array, we are just allocating space for its elements; no
values are stored in the array. There are three ways to store values in an array.

by - Hari Krishna
Page 9

Initializing Arrays during Declaration:

The elements of an array can be initialized at the time of declaration, just


as any other variable. When an array is initialized, we need to provide a value for
every element in the array.

Syntax: data_type array_name[size]={list of values};

Example: int marks[5]={ 90 , 45, 67, 85, 78};

int marks[5] ={90, 45};

Inputting Values from the Keyboard:

An array can be initialized by inputting values from the keyboard at the


time of runtime. In this method, a while/do–while or a for loop and scanf function
is executed to input the value for each element of the array.

Example: int i, marks[10];

for(i = 0; i < 10; i++)

scanf(“%d”, &marks[i]);

Assigning Values to Individual Elements:

The third way is to assign values to individual elements of the array by


using the assignment operator. Any value that evaluates to the data type as that of
the array can be assigned to the individual array element.

Example: marks[3] = 100;

by - Hari Krishna
Page 10

3 types of arrays
One-dimensional array
Two-dimensional array
Multi-dimensional array

Single Dimensional Array:

A single dimension array holds various elements of the same data type.
To identify and find the value of a particular component, we use the array
name and the value of an index element.
Array in C, is always used with only one subscript ([]).

Declaration of an array:

Data type- the kind of values it can store.


for example, int, char, float, double.
Name- to identify the array.
Size- the maximum number of values that the array can hold.

Syntax: data-type array_name[size];

Example: int marks[10];

Memory representation of an array of 10 elements

by - Hari Krishna
Page 11

Program:

#include <stdio.h>
int main()
{
int numbers[5];
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;
for(int i=0; i<5; i++)
{
printf("numbers[%d] = %d\n", i, numbers[i]);
}
return 0;
}

Output:

numbers[0] = 10
numbers[1] = 20
numbers[2] = 30
numbers[3] = 40
numbers[4] = 50

by - Hari Krishna
Page 12

Two-Dimensional Array in C:

The two-dimensional array can be defined as an array of arrays.


The 2D array is organized as matrices which can be represented as the
collection of rows and columns.
2D arrays are created to implement a relational database lookalike data
structure.
It provides ease of holding the bulk of data at once which can be passed
to any number of functions wherever required.

Syntax:

data_type array_name[rows][columns];

Example:

int twodimen[4][3];
int arr[4][3]={{1,2,3},{2,3,4},{3,4,5},{4,5,6}};

by - Hari Krishna
Page 13

Program:

#include<stdio.h>
int main()
{
int i=0,j=0;
int arr[4][3]={{1,2,3},{2,3,4},{3,4,5},{4,5,6}};
//traversing 2D array
for(i=0;i<4;i++)
{
for(j=0;j<3;j++)
{
printf("arr[%d] [%d] = %d \n",i,j,arr[i][j]);
}//end of j
}//end of i
return 0;
}

Output:
arr [0][0] = 1
arr [0][1] = 2
arr [0][2] = 3

arr [1][0] = 2
arr [1][1] = 3
arr [1][2] = 4

arr [2][0] = 3
arr [2][1] = 4
arr [2][2] = 5

arr [3][0] = 4
arr [3][1] = 5
arr [3][2] = 6

by - Hari Krishna
Page 14

Multi-dimensional array:

A multi-dimensional array is an array with more than one level or


dimension. For example, a 2D array, or two-dimensional array, is an array of
arrays, meaning it is a matrix of rows and columns (think of a table).

int arr[3][4] = {
{0, 1, 2, 3} , /* initializers for row indexed by 0 */
{4, 5, 6, 7} , /* initializers for row indexed by 1 */
{8, 9, 10, 11} /* initializers for row indexed by 2 */
};

Program:

#include <stdio.h>
void arr(int x[][3]); //function prototype
int main ()
{
int a[2][3] = {{1,2,3}, {4,5,6}}; //initializing array
int b[2][3] = {1, 2, 3, 4, 5};
int c[2][3] = {{1, 2}, {4}};
printf("values in array a by row:\n");
arr(a);
by - Hari Krishna
Page 15

printf("values in array b by row:\n");


arr(b);
printf("values in array c by row:\n");
arr(c);
return 0;
} // end of main
void arr(int x[][3])
{
int i; //row counter
int j; //column counter
for (i = 0; i <= 1; ++i)
{
for (j = 0; j<= 2; ++j)
{
printf("%d", x[i][j]);
} //end of inner for
printf("\n");
} //end of outer for
}

Output:
values in array a by row:
1 2 3
4 5 6
values in array b by row:
1 2 3
4 5 0
values in array c by row:
1 2 0
4 0 0

by - Hari Krishna
Page 16

Operations on arrays:

There are a number of operations that can be preformed on arrays. These


operations include:

Traversing an Array: Traversing an array means accessing each and every


element of the array for a specific purpose. It prints all array elements one
after another.
Inserting an element: Inserting operation is performed to insert one or
more elements into the array. As per the requirements, an element can be
added at the beginning, end, or at any index of the array.
Deleting an element: Deleting an element from an array means removing
a data element from an already existing array and then reorganizes all of
the array elements.
Search operation: Search operation is performed to search an element in
the array based on the value or index.
Sort operation: Sort operation helps to arrange the data elements in either
Ascending or Descending order.
Merging two arrays: Merging two arrays in a third array means first
copying the contents of the first array into the third array and then copying
the contents of the second array into the third array.

by - Hari Krishna
Page 17

Structures:

Structure is a user defined data type that can store related information
(even of different data types) together.

Structure Declaration:

A structure is declared using the keyword struct followed by a structure


name.

Syntax: struct struct–name { data_type var–name; data_type var–


name; ............... };

Example: struct student {


int r_no;

char name[20];

float fees;

};

by - Hari Krishna
Page 18

Initialization of structures:

Initializing a structure means assigning some values to the members of the


structure.

Syntax:

struct struct_name

data_type member_name1;

data_type member_name2;

data_type member_name3;

.......................

}struct_var = {constant1, constant2, constant3,...};

Example:

struct student

int r_no;

char name[20];

char course[20];

float fees;

}stud1 = {01, "Rahul", "BTech", 45000};

by - Hari Krishna
Page 19

Program:

#include <stdio.h>
#include <string.h>
struct Person // create struct with person1 variable
{
char name[50];
int Id;
float salary;
} person1;
int main()
{
strcpy(person1.name, "Bavvy");
person1.Id = 1234; // assign values to other person1 variables
person1. salary = 50000;
printf("Name: %s\n", person1.name); // print struct variables
printf("Emp Id No.: %d\n", person1. Id);
printf("Salary: %.2f", person1.salary);
return 0;
}

Output:
Name: Bavvy
Emp Id No.: 1234
Salary: 50000.00

by - Hari Krishna
Page 20

Self-Referential Structures:

Self-referential structures are those structures that contain a reference to


the data of its same type. That is, a self-referential structure, in addition to other
data, contains a pointer to a data that is of the same type as that of the structure.

Example: struct node {

int val;

struct node *next;

};

Here, the structure node will contain two types of data: an integer val and
a pointer next. You must be wondering why we need such a structure. Actually,
self-referential structure is the foundation of other data structures.

There are two types of self-referential structure in C


1. Linear Self-Referential Structure.
2. Non-Linear Self-Referential Structure

Linear Self-Referential Structure: These structures create a linear data


structure such as stacks, queues and linked lists. In this, each member points to
the next member sequentially.

Program:

#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* next;

by - Hari Krishna
Page 21

};
void display (struct Node* temp)
{
while (temp)
{
printf(" %d ", temp->data);
temp= temp->next;
}
}
void main()
{
struct Node* head =NULL; // assign each node a null value to avoid any
refrence error

struct Node* second_node = NULL;


struct Node* third_node = NULL;
head = (struct Node*) malloc (sizeof(struct Node)); // defining three
nodes
second_node = (struct Node*)malloc(sizeof(struct Node));
third_node = (struct Node*)malloc(sizeof(struct Node));
head->data = 100; // assign data in first node
head->next = second_node; // Link first node with second
second_node->data = 200; // assign data to second node
second_node->next = third_node;
third_node->data = 300; // assign data to third node
third_node->next = NULL;
display(head); // calling the function to display value
}

Output:
100 200 300

by - Hari Krishna
Page 22

Non-Linear Self-Referential Structure: These structures create a non linear


data structure, such as trees and graphs. In this, each member can point to many
members.

Program:

#include<stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *left;
struct node *right;
};
struct node* createNode(int data)
{
struct node *newNode= (struct node *)malloc(sizeof(struct node));
newNode->data= data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
void inorder(struct node *temp)
{
if(temp) // traverse untill root is NULL
{
inorder(temp->left);
printf("%d ", temp->data);
inorder(temp->right);
}
else
return;
}

by - Hari Krishna
Page 23

void main()
{
struct node *root= createNode (10); // create root node
root->left= createNode(100); //making links to child nodes
root->right= createNode(200);
root->left->left= createNode(300); // making further connections
root->left->right= createNode(400);
root->right->left= createNode(500);
root->right->right= createNode(600);
printf("In Order Traversal of Binary Tree \n");
inorder(root); // calling inorder traversal function
}

Output:
In Order Traversal of Binary Tree
300 100 400 10 500 200 600

Unions:

Union is a collection of variables of different data types, that you can only
store information in one field at any one time.

Thus, unions are used to save memory. They are useful for applications that
involve multiple members, where values need not be assigned to all the members
at any one time.

Syntax: union union–name {

data_type var–name;

data_type var–name;

..................

};

by - Hari Krishna
Page 24

Program:

#include <stdio.h>
#include <string.h>
union Data
{
int i;
float f;
char str[20];
};
int main( )
{
union Data data;
data.i = 10;
data.f = 220.5;
strcpy( data.str, "C Programming");
printf( "data.i : %d\n", data.i);
printf( "data.f : %f\n", data.f);
printf( "data.str : %s\n", data.str);
return 0;
}

Output:
data.i : 1917853763
data.f : 4122360580327794860452759994368.000000
data.str : C Programming

by - Hari Krishna
Page 25

Pointers

A pointer is a variable that stores the memory address of another variable


as its value.

A pointer variable points to a data type (like int) of the same type, and is
created with the * operator.

Declaring Pointer Variables:

Syntax: data_type *ptr_name;

Example: int x= 10;

int * ptr = &x;

The ‘*’ informs the compiler that ptr is a pointer variable and the int
specifies that it will store the address of an integer variable.
The ‘&’ operator retrieves the address of x, and copies that to the contents
of the pointer ptr.

by - Hari Krishna
Page 26

Program:

#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: %x\n", &var );
/* address stored in pointer variable */
printf("Address stored in ip variable: %x\n", ip );
/* access the value using the pointer */
printf("Value of *ip variable: %d\n", *ip );
return 0;
}
Output:
Address of var variable: 1586877c
Address stored in ip variable: 1586877c
Value of *ip variable: 20

by - Hari Krishna
Page 27

Null Pointer

A NULL pointer which is a special pointer value and does not point to any
value.
This means that a NULL pointer does not point to any valid memory
address.

Syntax: int *ptr = NULL;

Program:
#include <stdio.h>
int main ()
{
int *ptr = NULL;
printf("The value of ptr is : %x\n", &ptr );
return 0;
}
Output: The value of ptr is: 0

by - Hari Krishna
Page 28

Generic Pointer

A generic pointer is a pointer variable that has void as its data type. The
void pointer, or the generic pointer, is a special type of pointer that can
point to variables of any data type.

Syntax: void *ptr;

Generic pointers are used when a pointer has to point to data of different
types at different time.

Pointer to Pointer

A pointer to a pointer is a form of multiple indirection, or a chain of


pointers. Normally, a pointer contains the address of a variable.
When we define a pointer to a pointer, the first pointer contains the address
of the second pointer, which points to the location that contains the actual
value.
It is also known as double pointer.

Syntax: int **p;

Example: int x=10;

int *px, **ppx;

px = &x; ppx = &px;

by - Hari Krishna
Page 29

Pointer and array in C:

Pointers are used for storing address of dynamically allocated arrays and
for arrays which are passed as arguments to functions.

Program:

#include <stdio.h>
int main()
{
int arr[] = { 10, 20, 30, 40, 50, 60 };
int* ptr = arr;

// sizof(int) * (number of element in arr[]) is printed


printf("Size of arr[] %ld\n", sizeof(arr));

// sizeof a pointer is printed which is same for all


// type of pointers (char *, void *, etc)
printf("Size of ptr %ld", sizeof(ptr));
return 0;
}

Output:

Size of arr[] : 24

Size of ptr : 8

by - Hari Krishna
Page 30

Pointer to Array:

Pointers are variables which stores the address of another variable.


When we allocate memory to a variable, pointer points to the address of
the variable.
Unary operator ( * ) is used to declare a variable and it returns the address
of the allocated memory.
Pointers to an array points the address of memory block of an array
variable.

Syntax: datatype *variable_name[size];

Program:

#include <stdio.h>
int main ()
{
int *arr[3];
int *a;
printf( "Value of array pointer variable : %d", arr);
printf( "Value of pointer variable : %d", &a);
return 0;
}

Output:

Value of array pointer variable : 1108507200

Value of pointer variable : 1108507192

by - Hari Krishna
Page 31

Array of Pointers in C:

A pointer array is a homogeneous collection of indexed pointer variables


that are references to a memory location.
It is generally used in C Programming when we want to point at
multiple memory locations of a similar data type in our C program.
We can access the data by dereferencing the pointer pointing to it.

Syntax: pointer_type *array_name [array_size];

Program:

#include <stdio.h>
int main()
{
int var1 = 100; // declaring some temp variables
int var2 = 200;
int var3 = 300;
int* ptr_arr[3] = { &var1, &var2, &var3 }; // array of
pointers to integers
for (int i = 0; i < 3; i++) // traversing using loop
{
printf("Value of var%d: %d\tAddress: %p\n", i + 1,
*ptr_arr[i], ptr_arr[i]);
}
return 0;
}

Output:

Value of var1: 100 Address: 0x7fff537b88e0

Value of var2: 200 Address: 0x7fff537b88e4

Value of var3: 300 Address: 0x7fff537b88e8

by - Hari Krishna
Page 32

Dynamic Memory Allocation

The process of allocating memory to the variables during execution of the


program or at run time is known as dynamic memory allocation.
Heap space is used in Dynamic Memory Allocation.
To allocate and deallocate a memory block during run-time we use 4
different library functions like-
1. malloc( )
2. calloc( )
3. realloc( )
4. free( )

malloc( )

Malloc method is used to dynamically allocate a single large block of


memory with the specified size.
It returns a pointer of type void which can be cast into a pointer of any
from.
It doesn’t Initialize memory at execution time so that it has initialized each
block with the default garbage value initially.

Synatx: ptr = (cast-type*) malloc(size-of-byte);

Example:

by - Hari Krishna
Page 33

Program:
#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));
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;
}

Output:
Enter number of elements:
3
Enter elements of array:
10
20
30
Sum=60

by - Hari Krishna
Page 34

calloc( )

Calloc method is used to dynamically allocate the specified number of


blocks of memory of the specified type.
It initializes each block with a default value ’0’

Syntax: ptr = (cast-type*) calloc(n, element_size);

Example:

Program:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n,i,*ptr,sum=0;
printf("Enter number of elements: ");
scanf("%d",&n);
ptr=(int*)calloc(n,sizeof(int)); //memory allocated using calloc
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);

by - Hari Krishna
Page 35

}
printf("Sum=%d",sum);
free(ptr);
return 0;
}

Output:
Enter number of elements: 3
Enter elements of array:
10
10
10
Sum=30

free( )

Free method is used to dynamically de-allocate the memory.


The memory allocated using functions malloc() and calloc() is not de-
allocated on their own. Hence the free() method is used, whenever the
dynamic memory allocation takes place.
It helps to reduce wastage of memory by freeing it.

Syntax: free(ptr)

by - Hari Krishna
Page 36

Example:

Program:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *ptr = (int *)malloc(sizeof(int));
*ptr = 5;
printf("*ptr = %d", *ptr);
free(ptr); // deallocating the memory
printf("\nptr = %d", ptr); // ptr now contains a garbage value address
ptr = NULL;// assigning NULL to escape the garbage value errors
printf("\nMemory freed at runtime!");
return 0;
}
Output: *ptr = 5

ptr = -1172241760
Memory freed at runtime!

by - Hari Krishna
Page 37

realloc( )

Realloc method is used to dynamically change the memory allocation of a


previously allocated memory.
If memory is not sufficient for malloc() or calloc(), you can reallocate the
memory by using realloc() function.

Syntax: ptr = realloc(ptr, newSize);

Example:

by - Hari Krishna
Page 38

Program:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *ptr;
int x = 20;
ptr = malloc(sizeof(int)); // allocating memory using malloc
ptr[0] = x;
printf("Value of ptr before memory reallocation : %d\n", ptr[0]);
ptr = realloc(ptr, 5 * sizeof(int)); // reallocating memory using realloc
printf("Value of ptr after memory reallocation : %d", ptr[0]);
return 0;
}

Output:
Value of ptr before memory reallocation: 20
Value of ptr after memory reallocation: 20

by - Hari Krishna
Page 39

Functions:

C enables its programmers to break up a program into segments commonly


known as functions, each of which can be written more or less
independently of the others.
Every function in the program is supposed to perform a well-defined task.
Therefore, the program code of one function is completely insulated from
the other functions.
Every function interfaces to the outside world in terms of how information
is transferred to it and how results generated by the function are transmitted
back from it.

In the figure, we can see that main() calls a function named func1(). Therefore,
main() is known as the calling function and func1() is known as the called
function

A function f that uses another function g is known as the calling function,


and g is known as the called function.
The inputs that a function takes are known as arguments.

by - Hari Krishna
Page 40

Function Declaration:

Function Declaration is a declaration statement that identifies a function’s


name, a list of arguments that it accepts, and the type of data it returns.

Syntax: return_data_type function_name(data_type variable1,


data_type variable2, ….);

Function Definition:

Function Definition consists of a function header that identifies the


function, followed by the body of the function containing the executable code for
that function.

Syntax: return_data_type function_name(data_type variable1,


data_type variable2,..)
{
.............
statements
.............
return(variable);
}

Function Call:

The function call statement invokes the function.


When a function is invoked, the compiler jumps to the called function to
execute the statements that are a part of that function.
Once the called function is executed, the program control passes back to
the calling function.

Syntax: variable_name = function_name(variable1, variable2, …);

by - Hari Krishna
Page 41

Passing Parameters to Functions:

There are two ways in which arguments or parameters can be passed to the
called function.

Call by value - The values of the variables are passed by the calling
function to the called function.
Call by reference - The addresses of the variables are passed by the calling
function to the called function.

Dynamically Allocated Arrays

Unlike a fixed array, where the array size must be fixed at compile time,
dynamically allocating an array allows us to choose an array length at
runtime.
A dynamic array is quite similar to a regular array, but its size is modifiable
during program runtime.
A dynamic array can expand its size even after it has been filled.
Dynamically allocated arrays are allocated on the heap at run time.

What is a dynamic array?

The dynamic array is a variable size list data structure.


It grows automatically when we try to insert an element if there is no
more space left for the new element.
It allows us to add and remove elements.
It allocates memory at run time using the heap. It can change its size
during run time.

by - Hari Krishna
Page 42

Operations on Dynamic Array:


Add Element in a Dynamic Array:

In the dynamic array, we can create a fixed-size array if we required to add


some more elements in the array.
Usually, it creates a new array of double size.
After that, it copies all the elements to the newly created array.

Delete an Element from a Dynamic Array:

If we want to remove an element from the array at the specified index, we


use the removeAt(i) method.
The method parses the index number of that element which we want to
delete.
After deleting the element, it shifts the remaining elements (elements that
are right to the deleted element) to the left from the specified index number.
We also use the remove() method that deletes an element from the end of
the array.
After shifting the elements, it stores 0 at the palace of the last element.

by - Hari Krishna
Page 43

Example: (malloc)

#include <stdio.h>
#include <stdlib.h>
typedef struct vector
{
int size;
int arr[];
}vector;
int main()
{
int n;
printf("Enter Size of the array: ");
scanf("%d", &n);
vector *ptr = (vector * ) malloc( sizeof (vector * ) + n * sizeof(int));
// This implies 'ptr->arr' can hold `n` integers.

by - Hari Krishna
Page 44

printf("Enter the elements (space/newline separated): ");


for (int i = 0; i < n; i++)
scanf("%d", ptr -> arr + i);
printf("Given array is: ");
for (int i = 0; i < n; i++)
printf("%d ", ptr -> arr[i]);
printf("\n");
free(ptr);
return 0;
}
Output:

Enter Size of the array: 10

Enter the elements (space/newline separated): 10 20 30 40 50 60 70 80 90 100

Given array is: 10 20 30 40 50 60 70 80 90 100

Example:2 calloc

#include <stdio.h>
#include <stdlib.h>
int main()
{
int n;
printf("Size of the array: ");
scanf("%d", &n);
int *arr = calloc(n, sizeof(int)); // Creating enough space for 'n' integers.
if (arr == NULL)
{
printf("Unable to allocate memory\n");

by - Hari Krishna
Page 45

return -1;
}
printf("Enter the elements (space/newline separated): ");
for (int i = 0; i < n; i++)
scanf("%d", arr + i); // Notice that, (arr + i) points to ith element
printf("Given array: ");
for (int i = 0; i < n; i++)
printf("%d ", *(arr + i)); // Dereferencing the pointer
printf("\n");
printf("Removing first element i.e., arr[0] = %d.\n", arr[0]);
for (int i = 1; i < n; i++)
arr[i - 1] = arr[i];
arr = realloc(arr, (n - 1) * sizeof(int));
printf("Modified Array: ");
for (int i = 0; i < n - 1; i++)
printf("%d ", arr[i]);
printf("\n");
free(arr);
return 0;
}
Output:

Size of the array: 5

Enter the elements (space/newline separated): 10 20 30 40 50

Given array: 10 20 30 40 50

Removing first element i.e., arr[0] = 10.

Modified Array: 20 30 40 50

by - Hari Krishna
Page 46

Representation of linear arrays in memory

The elements of Linear Array are stored in successive memory cells.


The computer does not keep track of the address of every element of LA,
but needs to keep track only the address of the first element of Linear
Array.

Properties of array:

There are some of the properties of an array that are listed as follows -

Each element in an array is of the same data type and carries the same size
that is 4 bytes.
Elements in the array are stored at contiguous memory locations from
which the first element is stored at the smallest memory location.
Elements of the array can be randomly accessed since we can calculate the
address of each element of the array with the given base address and the
size of the data element.

Representation of an array:

Memory allocation of an array

As stated above, all the data elements of an array are stored at contiguous
locations in the main memory.
The name of the array represents the base address or the address of the first
element in the main memory.
Each element of the array is represented by proper indexing.

by - Hari Krishna
Page 47

We can define the indexing of an array in the below ways:

1. 0 (zero-based indexing): The first element of the array will be arr[0].


2. 1 (one-based indexing): The first element of the array will be arr[1].
3. n (n - based indexing): The first element of the array can reside at any
random index number.

Length of Arry: 5
First Index: 0
Last Index: 4
Basic operations:

Traversal - This operation is used to print the elements of the array.


Insertion - It is used to add an element at a particular index.
Deletion - It is used to delete an element from a particular index.
Search - It is used to search an element using the given index or by the
value.
Update - It updates an element at a particular index.

by - Hari Krishna
Page 48

Insertion operation:

This operation is performed to insert one or more elements into the array.
As per the requirements, an element can be added at the beginning, end, or
at any index of the array.
Now, let's see the implementation of inserting an element into the array.

Example:

#include <stdio.h>
int main()
{
int arr[20] = { 10, 20, 30, 40 };
int i, x, pos, n = 5;
printf("Array elements before insertion\n");
for (i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
x = 50; // element to be inserted
pos = 4;
n++;
for (i = n-1; i >= pos; i--)
arr[i] = arr[i - 1];
arr[pos - 1] = x;
printf("Array elements after insertion\n");
for (i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
return 0;
}

Output:

Array elements before insertion


10 20 30 40
Array elements after insertion
10 20 30 40 50

by - Hari Krishna
Page 49

Deletion operation:

As the name implies, this operation removes an element from the array and
then reorganizes all of the array elements.

Example:

#include <stdio.h>
void main()
{
int arr[] = {100, 200, 300, 400, 500};
int k = 30, n = 5;
int i, j;
printf("Given array elements are :\n");
for(i = 0; i<n; i++)
{
printf("arr[%d] = %d, ", i, arr[i]);
}
j = k;
while( j < n)
{
arr[j-1] = arr[j];
j = j + 1;
}
n = n -1;
printf("\nElements of array after deletion:\n");
for(i = 0; i<n; i++)
{
printf("arr[%d] = %d, ", i, arr[i]);
}
}

Output:

Given array elements are:


arr[0] = 100, arr[1] = 200, arr[2] = 300, arr[3] = 400, arr[4] = 500,
Elements of array after deletion:
arr[0] = 100, arr[1] = 200, arr[2] = 300, arr[3] = 400

by - Hari Krishna
Page 50

Search operation:

Search operation is performed to search an element in the array based on


the value or index.

Example:

#include <stdio.h>
void main()
{
int arr[10] = { 10, 20, 30, 40, 50,60,70,80,90,100};
int item = 70, i, j=0 ;
printf("Given array elements are :\n");
for(i = 0; i<10; i++)
{
printf("arr[%d] = %d, ", i, arr[i]);
}
printf("\n Element to be searched = %d", item);
while( j < 10)
{
if( arr[j] == item )
{
break;
}
j = j + 1;
}
printf("\n Element %d is found at %d position", item, j+1);
}

Output:

Given array elements are :


arr[0] = 10, arr[1] = 20, arr[2] = 30, arr[3] = 40, arr[4] = 50, arr[5] = 60,
arr[6] = 70, arr[7] = 80, arr[8] = 90, arr[9] = 100,
Element to be searched = 70
Element 70 is found at 7 position

by - Hari Krishna
Page 51

Update operation:

Update operation is performed to update an existing array element located


at the given index.

Example:

#include <stdio.h>
void main()
{
int arr[5] = {18, 30, 15, 70, 12};
int item = 50, i, pos = 3;
printf("Given array elements are :\n");
for(i = 0; i<5; i++)
{
printf("arr[%d] = %d, ", i, arr[i]);
}
arr[pos-1] = item;
printf("\n Array elements after pupation :\n");
for(i = 0; i<5; i++)
{
printf("arr[%d] = %d, ", i, arr[i]);
}
}

Output:

Given array elements are:

arr[0] = 10, arr[1] = 20, arr[2] = 30, arr[3] = 40, arr[4] = 50,

Array elements after updation :

arr[0] = 10, arr[1] = 20, arr[2] = 60, arr[3] = 40, arr[4] = 50,

by - Hari Krishna
Page 52

Performance analysis of an algorithm

Algorithm

Algorithm is a blueprint to write a program to solve a particular problem.


An algorithm is a set of instructions for solving a problem or
accomplishing a task.
Algorithms are mainly used to achieve software re-use.

The performance analysis of an algorithm is done in 2 ways

1. Time Complexity
2. Space Complexity

Space Complexity

The space complexity of an algorithm is the amount of computer memory


that is required during the program execution.

The space needed by a program depends on 2 parts -

Fixed part: The space needed for storing instructions, constants, variables,
and structures variables (like arrays and structures).
Variable part: The space needed for recursion stack, and for structured
variables that are allocated space dynamically during runtime of a program.

The space needed by both parts may varies from problem to problem.

by - Hari Krishna
Page 53

Time Complexity

The time complexity of an algorithm is basically the running time of a


program execution.

There are 3 cases of time complexities

Worst-case running time

This denotes the behavior of the algorithm with respect to the worst
possible case of the input instance.
It gives us an assurance that the algorithm will never go beyond this time
limit.

Average-case running time

The average time of an algorithm is an estimate of the running time for an


‘average’ input.
It assumes that all inputs of a given size are equally likely.

Best-case running time

The ‘best-case performance’ is used to analyze an algorithm under optimal


conditions.

Notations

Big O notation (O):

This notation provides an upper bound on the growth rate of an


algorithm’s running time or space usage.
It represents the worst-case scenario, i.e., the maximum amount of time
or space an algorithm may need to solve a problem.

by - Hari Krishna
Page 54

If f(n) and g(n) are the functions defined on a positive integer number n,
then f(n) = O(g(n)).
For example, if an algorithm’s running time is O(n), then it means that
the running time of the algorithm increases linearly with the input size n
or less.

Omega notation (Ω):

This notation provides a lower bound on the growth rate of an algorithm’s


running time or space usage.
It represents the best-case scenario, i.e., the minimum amount of time or
space an algorithm may need to solve a problem.
For example, if an algorithm’s running time is Ω(n), then it means that
the running time of the algorithm increases linearly with the input size n
or more.

by - Hari Krishna
Page 55

Theta notation (Θ):

This notation provides both an upper and lower bound on the growth rate
of an algorithm’s running time or space usage.
It represents the average-case scenario, i.e., the amount of time or space
an algorithm typically needs to solve a problem.
For example, if an algorithm’s running time is Θ(n), then it means that
the running time of the algorithm increases linearly with the input size n.

by - Hari Krishna
Page 56

Algorithm Efficiency:

The efficiency of an algorithm is expressed in terms of the number of


elements that has to be processed. So, if n is the number of elements, then the
efficiency of an algorithm can be stated as:

f(n) = efficiency

Linear loops

for(i = 0; i < n; i++)


statement block;
f(n) = n

Logarithmic Loops

for(i = 1; i < n; i *= 2)
statement block;
f(n) = log n

Linear logarithmic

for(i = 0;i < n; i++)


for(j = 1;j < n; j *= 2)
statement block;
f(n) = n log n

Quadratic loop

for(i = 0; i < n; i++)


for(j = 1; j < n; j++)
statement block;
f(n) = n * n

by - Hari Krishna
Page 57

Dependent Quadratic

for(i = 0;i < n; i++)


for(j = 1;j < i; j++)
statement block;
f(n) = n (n + 1) / 2

by - Hari Krishna

You might also like