Académique Documents
Professionnel Documents
Culture Documents
UNIT-I
Efficiency of an algorithm can be analyzed at two different stages, before implementation and after
implementation. They are the following
A Priori Analysis this is a theoretical analysis of an algorithm. Efficiency of an algorithm is measured
by assuming that all other factors, for example, processor speed, are constant and have no effect on the
implementation.
A Posterior Analysis this is an empirical analysis of an algorithm. The selected algorithm is
implemented using programming language. This is then executed on target computer machine. In this
analysis, actual statistics like running time and space required are collected.
Algorithm analysis deals with the execution or running time of various operations involved. The running time of an
operation can be defined as the number of computer instructions executed per operation.
What is Algorithm?
An algorithm is a finite set of instructions or logic, written in order, to accomplish a certain
predefined task. Algorithm is not the complete code or program, it is just the core logic(solution) of a
problem, which can be expressed either as an informal high level description as pseudocode or using
a flowchart.
An algorithm is said to be efficient and fast, if it takes less time to execute and consumes less memory
space. The performance of an algorithm is measured on the basis of following properties :
1. Time Complexity
2. Space Complexity
Space Complexity
It is the amount of memory space required by the algorithm, during the course of its execution. Space
complexity must be taken seriously for multi-user systems and in situations where limited memory is
available.
Instruction Space: Its the space required to store the executable version of the program. This space is
fixed, but varies depending upon the number of lines of code in the program.
Data Space: Its the space required to store all the constants and variables value.
Environment Space: Its the space required to store the environment information needed to resume the
suspended function.
Time Complexity
Time Complexity is a way to represent the amount of time needed by the program to run to completion. We
will study this in details in our section. Similarly it can be based on
Number of inputs
Number of outputs
Type of selecting statement
Asymptotic analysis:
The definition of asymptotic is a line that approaches a curve but never touches. A curve and a line that get closer
but do not intersect are examples of a curve and a line that are asymptotic to each other)
Asymptotic analysis of an algorithm refers to defining the mathematical boundation/framing of its run-
time performance. Using asymptotic analysis, we can very well conclude the best case, average case, and
worst case scenario of an algorithm.
Asymptotic analysis is input bound i.e., if there's no input to the algorithm, it is concluded to work in a
constant time. Other than the "input" all other factors are considered constant.
Asymptotic analysis refers to computing the running time of any operation in mathematical units of
computation.
For example, the running time of one operation is computed as f(n) and may be for another operation it is
computed as g(n2). This means the first operation running time will increase linearly with the increase
in n and the running time of the second operation will increase exponentially when n increases. Similarly,
the running time of both operations will be nearly the same if n is significantly small.
Usually, the time required by an algorithm falls under three types
Best Case Minimum time required for program execution.
Average Case Average time required for program execution.
Worst Case Maximum time required for program execution.
Asymptotic Notations:
Following are the commonly used asymptotic notations to calculate the running time complexity of an algorithm.
Notation
Notation
Notation
Big Oh Notation, ():
The notation (n) is the formal way to express the upper bound of an algorithm's running time. It measures the
worst case time complexity or the longest amount of time an algorithm can possibly take to complete.
(f(n)) = { g(n) : there exists c > 0 and n0 such that f(n) c.g(n) for all n > n0. }
(f(n)) = { g(n) if and only if g(n) = (f(n)) and g(n) = (f(n)) for all n > n0. }
DATA STRUCTURE:
Data Structure is a way of collecting and organizing data in such a way that we can perform
operations on these data in an effective way. Data Structures is about rendering data elements in terms of
some relationship, for better organization and storage.
Example:
For example, we have data player's name "sachin" and age 26. Here "sachin" is of String data
type and 26 are of integer data type. Similarly for organizing data will be look lik student name, age, roll
no, address and other details.
We can organize this data as a record like Player record. Now we can collect and store player's records in a
file or database as a data structure. For example: "Dhoni" 30, "Gambhir" 31, "Sehwag" 33
In simple language, Data Structures are structures programmed to store ordered data, so that various
operations can be performed on it easily.
Algorithm + data
(Or)
structure=program
A data structure is a specialized format for organizing and storing data. So that we can easily access and
retrieve data in appropriate manner.
General data structure types include the array, the file, the record, the table, the tree, and so on.
Any data structure is designed to organize data to suit a specific purpose so that it can be accessed and
worked with in appropriate ways.
A data item in a nonlinear data structure could be attached to several other data elements to reflect a special
relationship among them and all the data items cannot be traversed in a single run.
Data structures like trees and graphs and tables are some examples of widely used nonlinear data structures.
A tree is a data structure that is made up of a set of linked nodes, which can be used to represent a
hierarchical relationship among data elements.
A graph is a data structure that is made up of a finite set of edges and vertices. Edges represent connections
or relationships among vertices that stores data elements.
Table means combination of rows and columns collected together.
Difference between Linear and Nonlinear Data Structures
Main difference between linear and nonlinear data structures lie in the way they organize data elements.
In linear data structures, data elements are organized sequentially and therefore they are easy to implement
in the computers memory. In nonlinear data structures, a data element can be attached to several other data
elements to represent specific relationships that exist among them.
Due to this nonlinear structure, they might be difficult to be implemented in computers linear memory
compared to implementing linear data structures.
Data structures
Traversing
o Searching
Insertion
Deletion
Sorting
Merging
Arrays:
Why?
In some cases it is necessary to deal or use many variables so for that we are using the concept of arrays.
We can write the program by considering minimum number of variables but when we want to use multiple variables
if we declare that variables individually program complexity increases to overcome that we are preferring arrays
Definition:
An array is a collection of data items, all of the same type, accessed using a common name. array index starts
from 0(zero) onwards
or
Arrays a kind of data structure that can store a fixed-size sequential collection of elements of the same type. An
array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables
of the same type.
Instead of declaring individual variables, such as number0, number1, ..., and number99, you declare one array
variable such as numbers and use numbers[0], numbers[1], and ..., numbers[99] to represent individual variables. A
specific element in an array is accessed by an index.
All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the
highest address to the last element.
Declaring Array:
Syntax:
Data type array name [subscript];
Another name for subscript can be called with index also.
Where data type------- indicates type of data
Array name indicates name of an array to identify
Subscript indicates size of an array.
Example:
int a[5];
This is called one dimensional array where data type is int, array name is a and subscript is 5 which it means the can able to store 5 elements.
Array initialization:
Assigning values before processing can be known Arrays. Initialization can be classified into 4 ways. The following
are to be
1. Complete initialization
2. Partial initialization
3. Initialization without size
4.String initialization
Complete initialization:
The process of assigning values completely according to or based on size of an array can be known as
complete initialization.
You can initialize an array in C either one by one or using a single statement as follows
Syntax:
Data type array name [index]={value1,value2,value3,.valuen};
values
Here data type is integer so it occupies two (2) bytes for each and every location.
Partial initialization:
The process of assigning values partially according to or based on size of an array can be known as
complete initialization.
In other words 10 20 30 40 50 we are not
going to assign values in
complete manner.
You can initialize an array in C either one by one or using a single statement as follows
Syntax:
Data type array name [index]={value1,value2,value3,.value n};
Example:
int bit [5] = {10,20,30};
Which means bit [0] = 10, bit [1] = 20, bit [2] = 30
Here we assigned only 3 values but actual size of an array is or it can able to store five elements but
instead we only assigned 3 values. This type of initial can be known as Partial initialization.
Which means bit [0] = 10, bit [1] = 20, bit [2] = 30, bit [3] = 40, bit [4] = 50, bit [5] = 60
Here we assigned only 6 values but actual size of an array not defined so according to user requirement we
may also assign vales and memory will be allocated whatever the values entered by user. This type of initialization
can be known as initialization without size.
Types of an array:
There are 2 types of C arrays. They are,
1. One dimensional array
2. Multi dimensional array
Two dimensional array
N dimensional array and so on
1. Single or One Dimensional array is used to represent and store data in a linear form.
Syntax:
Syntax:
Data type array name [subscript1] [subscript2];;
Where data type------- indicates type of data
Array name indicates name of an array to identify
Subscript 1 indicates number of rows, Subscript 2 indicates number of columns
int main()
{
int i;
int arr[5] = {10,20,30,40,50};
for (i=0;i<5;i++)
{
// Accessing each variable
printf("value of arr[%d] is %d \n", i, arr[i]);
}
}
Output:
value of arr[0] is 10
value of arr[1] is 20
value of arr[2] is 30
value of arr[3] is 40
value of arr[4] is 50.
int main()
{
int i,j;
// declaring and Initializing array
int arr[2][2] = {10,20,30,40};
/* Above array can be initialized as below also
arr[0][0] = 10; // Initializing array
arr[0][1] = 20;
arr[1][0] = 30;
arr[1][1] = 40; */
for (i=0;i<2;i++)
{
for (j=0;j<2;j++)
{
// Accessing variables
printf("value of arr[%d] [%d] : %d\n",i,j,arr[i][j]);
}
}
}
Output:
value of arr[0] [0] is 10
value of arr[0] [1] is 20
value of arr[1] [0] is 30
value of arr[1] [1] is 40
They are a dynamic in nature which allocates the memory when required.
Singly linked lists contain nodes which have a data part as well as an address part i.e. next, which points to
the next node in sequence of nodes. The operations we can perform on singly linked lists are insertion, deletion
and traversal.
In a doubly linked list, each node contains two links the first link points to the previous node and the next
link points to the next node in the sequence.
In the circular linked list the last node of the list contains the address of the first node and forms a circular
chain.
4. Array vs Linked-List
Types
Display Elements
We are learning this topic using c programming. Linked list is a type of data structure provided in C
language to make use of pointer efficiently.
2. It is very common data structure that is used to create tree, graph and other abstract data types.
Linked list comprise of group or list of nodes in which each node have link to next node to form a chain
2. Each node Consist of two Parts Data Part & Pointer Part
3. Node A has two part one data part which consists of the 5 as data and the second part which contain the
address of the next node (i.e it contain the address of the next node)
No Element Explanation
2 Address Field in Node Address field in node is used to keep address of next node
3 Data Field in Node Data field in node is used to hold data inside linked list.
We can represent linked list in real life using train in which all the buggies are nodes and two
coaches are connected using the connectors.
In case of railway we have peoples seating arrangement inside the coaches is called as data part of lined list
while connection between two buggies is address filed of linked list.
Like linked list, trains also have last coach which is not further connected to any of the buggie. Engine can
be called as first node of linked list
Linked List of advantages:
5. Linear Data Structures such as Stack, Queue can be easily implemented using Linked list
1. Wastage of memory
2. No random access
3. Time consuming
Explanation:
1. It is most basic type of Linked List in C.
4. First Node does not have predecessor while last node does not have any successor.
6. In the above Linked List We have 3 types of nodes.(first, middle, last nodes)
7. In Singly Linked List access is given only in one direction thus Accessing Singly Linked is
Unidirectional.
8. We can have multiple data fields inside Node but we have only single Link for next node.
No Field Significance
1 data It is Integer Part for Storing data inside Linked List Node
3. One value container stores actual data and another stores address of the another structure i.e
(Square box having two partitions)
4. We have declared a structure and also created 1 very first structure called Start.
5. Very first node Start contain 1 field for storing data and another field for address of another structure
6. As this is very first node or Structure, we have specified its next field with NULL value.
NULL means NOTHING , if next node is unavailable then initialize variable name to NULL.
void creat()
{
char ch;
do
{
struct node *new_node,*current;
new_node=(struct node *)malloc(sizeof(struct node));
if(start==NULL)
{
start=new_node;
current=new_node;
}
else
{
current->next=new_node;
current=new_node;
}
printf("nDo you want to creat another : ");
ch=getche();
}while(ch!='n');
}
current->next = new_node;
1. Introduction:
Consider the Singly Linked list node structure. Traversing linked list means visiting each and every node of the
singly linked list. Following steps are involved while traversing the singly linked list
2. Fetch the data from the node and perform the operations such as arithmetic operation or any operation
depending on data type.
3. After performing operation, advance pointer to next node and perform all above steps on Visited node.
do {
// Do Your Operation
// Statement ...1
// Statement ...2
// Statement ...3
// Statement ...n
}while(temp!=NULL);
}while(temp!=NULL);
Explanation:
Initially
temp = start;
1. Store Address of Starting node into temp, print data stored in the node temp. ## Refer : Different
Syntax and Terms in Linked List
2. Once Data stored in the temp is printed, move pointer to the next location so that temp will contain
address of 2nd node.
[box]
Special Note:
In Singly Linked List Program, do not change start index un-necessarily because we must have something that
can store address of Head node.
2. Traversal Starts from Very First node. We cannot modify the address stored inside global variable
start thus we have to declare one temporary variable -temp of type node.
3. In order to traverse from start to end you should assign Address of Starting node in Pointer
variable i.e temp
struct node *temp; //Declare temp
temp = start; //Assign Starting Address to temp
Now we are checking the value of pointer (i.e temp). If the temp is NULL then we can say that last node is
reached.
while(temp!=NULL)
{
printf("%d",temp->data);
temp=temp->next;
}
See below dry run to understand the complete code and consider the linked list shown in the above figure
Iteration 4 7 NULL
struct node
Explanation
Declaring Variable of Type Node.
*new_node,*current; of Terms :
Declared a global variable of type node. start is used to refer the
*start = NULL;
starting node of the linked list.
Access the 2nd Node of the linked list. This term contain the
start->next address of 2nd node in the linked list. If 2nd node is not present
then it will return NULL.
After the execution of this statement, 2nd node of the linked list will
start = start->next;
be called as starting node of the linked list.
if(new_node == NULL)
printf("nFailed to Allocate Memory");
if(start==NULL)
{
start=new_node;
current=new_node;
}
else
{
new_node->next=start;
start=new_node;
}
}
Diagram :
Attention :
1. If starting node is not available then Start = NULL then following part is executed
if(start==NULL)
{
start=new_node;
current=new_node;
}
2. If we have previously created First or starting node then else part will be executed to insert node at
start
else
{
new_node->next=start;
start=new_node;
}
4. Node is to be inserted at Last Position so we need to traverse SLL upto Last Node.
if(new_node == NULL)
printf("nFailed to Allocate Memory");
if(start==NULL)
{
start=new_node;
current=new_node;
}
else
{
temp = start;
while(temp->next!=NULL)
{
temp = temp->next;
}
temp->next = new_node;
}
}
Attention :
1. If starting node is not available then Start = NULL then following part is executed
if(start==NULL)
{
start=new_node;
current=new_node;
}
3. Traverse Upto Last Node., So that temp can keep track of Last node
else
{
temp = start;
while(temp->next!=NULL)
{
temp = temp->next;
}
4. Make Link between Newly Created node and Last node ( temp )
temp->next = new_node;
new_node->next=NULL;
st :
printf("nEnter the position : ");
scanf("%d",&pos);
if(pos>=(length()+1))
{
printf("nError : pos > length ");
goto st;
}
if(start==NULL)
{
start=new_node;
current=new_node;
}
else
{
temp = start;
for(i=1;i< pos-1;i++)
{
temp = temp->next;
}
temp1=temp->next;
temp->next = new_node;
new_node->next=temp1;
}
}
Explanation :
Step 1 : Get Current Position Of temp and temp1 Pointer.
temp = start;
for(i=1;i< pos-1;i++)
{
temp = temp->next;
}
Step 2 :
temp1=temp->next;
Step 3 :
temp->next = new_node;
Step 4 :
new_node->next = temp1
Program :
void del_beg()
{
struct node *temp;
temp = start;
start = start->next;
free(temp);
printf("nThe Element deleted Successfully ");
}
Attention:
Step 1: Store Current Start in another Temporary Pointer
temp = start;
Step 3 : Delete temp i.e Previous Starting Node as we have Updated Version of Start Pointer
free(temp);
Searching of a node:.
temp = start;
while(temp!=NULL)
{
if(temp->data == num)
return(temp); //Found
temp = temp->next;
}
if(flag == 0)
return(start); // Not found
}
We know the logic for traversing through the linked list in C Programming.
Function for counting the singly linked nodes is very similar to display (), only difference is that
instead of printing data we are incrementing length variable.
Void count ()
{
struct node *temp;
int length = 0;
temp = start;
while(temp!=NULL)
{
length++;
temp=temp->next;
}
printf("nLength of Linked List : %d",length);
}
void creat()
{
char ch;
do
{
struct node *new_node,*current;
if(start==NULL)
{
start=new_node;
current=new_node;
}
else
{
current->next=new_node;
current=new_node;
}
void display()
{
struct node *new_node;
printf("The Linked List : n");
new_node=start;
while(new_node!=NULL)
{
printf("%d--->",new_node->data);
new_node=new_node->next;
}
printf("NULL");
}
//----------------------------------------------------
void main()
{
create();
display();
}
//----------------------------------------------------
Output :
Enter the data : 10
Do you want to creat another : y
Enter the data : 20
Do you want to creat another : y
2. One address field for storing address of next node to be followed and second address field contain
address of previous node linked to it.
3. So Two way access is possible i.e We can start accessing nodes from start as well as from last .
4. Like Singly Linked List also only Linear but Bidirectional Sequential movement is possible.
Explanation:
1. Doubly Linked List is most useful type of Linked List.
2. In DLL we have facility to access both next as well as previous data using next link and previous
link.
3. In the above diagram , suppose we are currently on 2nd node i.e at 4 then we can access next and
previous data using
To Access Next Data : curr_node->next->data
To Access Previous Data : curr_node->previous->data
4. We have to always maintain start node, because it is the only node that is used to keep track of
complete linked list.
struct node {
int data;
int key;
int length() {
int length = 0;
struct node *current;
return length;
while(ptr != NULL) {
printf("(%d,%d) ",ptr->key,ptr->data);
ptr = ptr->next;
}
printf(" ]");
}
while(ptr != NULL) {
//print data
printf("(%d,%d) ",ptr->key,ptr->data);
printf(" ]");
}
//create a link
struct node *link = (struct node*) malloc(sizeof(struct node));
link->key = key;
link->data = data;
if(isEmpty()) {
//make it the last link
last = link;
//create a link
struct node *link = (struct node*) malloc(sizeof(struct node));
link->key = key;
link->data = data;
if(isEmpty()) {
//make it the last link
last = link;
} else {
//make link a new last link
last->next = link;
head = head->next;
//return the deleted link
return tempLink;
}
last = last->prev;
printf("\n");
printf("\nList (Last to first): ");
displayBackward();
Output:
List (First to Last):
[ (6,56) (5,40) (4,1) (3,30) (2,20) (1,10) ]
2. In Circular Linked List Address field of Last node contain address of First Node.
4. Linked List is made circular by linking first and last node , so it looks like circular chain [ shown in
Following diagram ].
5. Two way access is possible only if we are using Doubly Circular Linked List
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
struct node {
int data;
int key;
bool isEmpty() {
return head == NULL;
}
int length() {
int length = 0;
current = head->next;
while(current != head) {
length++;
current = current->next;
}
return length;
}
//create a link
struct node *link = (struct node*) malloc(sizeof(struct node));
link->key = key;
link->data = data;
if (isEmpty()) {
head = link;
head->next = head;
} else {
//point it to old first node
link->next = head;
if(head->next == head) {
head = NULL;
return tempLink;
}
while(ptr->next != ptr) {
printf("(%d,%d) ",ptr->key,ptr->data);
ptr = ptr->next;
}
}
printf(" ]");
}
main() {
insertFirst(1,10);
insertFirst(2,20);
insertFirst(3,30);
insertFirst(4,1);
insertFirst(5,40);
insertFirst(6,56);
//print list
printList();
while(!isEmpty()) {
struct node *temp = deleteFirst();
printf("\nDeleted value:");
printf("(%d,%d) ",temp->key,temp->data);
}
Output:
Original List:
[ (6,56) (5,40) (4,1) (3,30) (2,20) ]
Deleted value :(6,56)
Deleted value :(5,40)
Deleted value:(4,1)
Deleted value:(3,30)
Deleted value:(2,20)
Deleted value:(1,10)
List after deleting all items:
[ ]
However, for any polynomial operation, such as addition or multiplication of polynomials , linked list
representation is more easier to deal with.
The real life application where the circular linked list is used is our Personal Computers, where multiple
applications are running.
All the running applications are kept in a circular linked list and the OS gives a fixed time slot to all for running.
The Operating System keeps on iterating over the linked list until all the applications are completed.
Sparse matrix is a matrix which contain Sparse matrix representation s very few non-zero elements.
When a sparse matrix is represented with 2-dimensional array, we waste lot of space to represent that
matrix.
For example, consider a matrix of size 100 X 100 containing only 10 non-zero elements. In this matrix,
only 10 spaces are filled with non-zero values and remaining spaces of matrix are filled with zero.
That means, totally we allocate 100 X 100 X 2 = 20000 bytes of space to store this integer matrix. And to
access these 10 non-zero elements we have to make scanning for 10000 times.
Sparse Matrix Representations can be done in many ways following are two common representations:
1. Array representation
2. Linked list representation
Or