0% found this document useful (0 votes)
13 views

Module 1_DSA

Data structure module 1

Uploaded by

Lalli Krishnan
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
13 views

Module 1_DSA

Data structure module 1

Uploaded by

Lalli Krishnan
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 112

COURSE

DATA STRUCTURES & ALGORITHMS 3


TITLE CREDITS
COURSE COURSE
3CS 1006 Core L-T-P 2-0-2
CODE CATEGORY
Approval LEARNING
Version 1.0 ACM BTL-3
Details LEVEL
ASSESSMENT SCHEME
Semester
During Semester Assessment (DSA) End
Examination
MSE DSA Components Attendance SEE

10% 35% 5% 50%


This course introduces fundamental concepts of data structure and algorithms. It
includes the concepts of stacks, queues, linked lists, trees, graphs, and hash tables.
Course It also includes the different searching and sorting techniques. It also helps learn
Description writing algorithms in a step-by-step approach for solving problems with the help
of fundamental data structures.
Assessment Methods

Sl.No Assessmen Description Weightage Course Outcomes To be Duration/Time


t Type in marks Assessed line
CO CO CO CO CO
1 2 3 4 5
1 QZ Quiz 5 1 Hr
Mid Semester
2 MSE 10 1 Hr
Exam
3 AS Assignment 10 2 Hrs
Coursera
4 CC 5 10 Hrs
Course
5 MSE LAB MSE Lab 15 2 Hrs
6 AT Attendance 5 45 Hrs
Semester End-
7 SEE 50 3 Hrs
Examination
1.To impart the basic concepts of data structures and algorithms.
2.To understand concepts about searching and sorting techniques
Course
3.To understand basic concepts about stacks, queues, lists, trees and graphs.
Objective
4.To learn to write algorithms for solving problems with the help of
fundamental data structure
1. Demonstrate an understanding of Arrays and Linked Lists. Analyze the
time and space complexity of algorithms
2. For a given problem of Stacks and Queues student will be able to
implement it and analyse the same to determine the time and computation
complexity.
Course
3. Student will be able to implement searching and sorting algorithms and
Outcome
analyse their performance in term of Space and Time complexity.
4. Upon completion student will be able to implement different types of tree
algorithms.
5. Student will be able to implement Graph search and traversal algorithms
and determine the time and computation complexity
MODULE 1: Introduction, Arrays and Linked Lists

Introduction to data structures, Need for Data Structures.


Types of data structures: Linear and Nonlinear. Operations on
data structures: Insertion, Deletion, Traversal etc.
Arrays: One-dimensional arrays, Multidimensional arrays.
Operations on arrays. CO-1
Linked lists: Creation of single linked list, double linked list,
circular linked list, and operations on them.
Introduction to algorithms-Definition and Characteristics,
Analysis of algorithms- Asymptotic notations for time and space
complexities with examples.
What is Data Structure?

• A data structure defines a way of organizing all data items that


considers not only the elements stored but also their relationship to
each other. The term data structure is used to describe the way data
is stored.
• It is also used for processing, retrieving, and storing data.
What is the need of Data Structure?
Data structures are essential for two main reasons: they make the code more efficient, and they
make the code easier to understand. Some specific reasons why data structures are important
include:
1.Improved Time Complexity: Using appropriate data structures can lead to better time
complexity, making it possible to solve problems more quickly. For example, searching for an
element in a sorted array is faster than searching for it in an unsorted array.
2.Better Space Complexity: Data structures can help to reduce the amount of memory needed to
store data. For example, using a linked list instead of an array can reduce the amount of memory
needed to store the same data.
3.Efficient Data Retrieval: Data structures make it easier to retrieve specific data efficiently. For
example, a hash table can retrieve data in constant time, while searching through an unsorted array
takes linear time.
4.Better Data Management: Data structures make it easier to manage and manipulate data. For
example, a stack can be used to implement an undo functionality in an application.
5.Solving Complex Problems: Data structures can provide the foundation for efficient algorithms,
making it possible to solve complex problems in a reasonable amount of time. For example, graph
algorithms can be used to find the shortest path between two points or to find the minimum
spanning tree of a graph.
Data Structures Taxonomies
Primitive Data Structures are the basic data structures that directly operate upon
the machine instructions.
Non-primitive data structures are more complicated data structures and are
derived from primitive data structures. They emphasize on grouping same or
different data items with relationship between each data item.

Linear data structures organize their data elements in a linear fashion, where
data elements are attached one after the other. Linear data structures are very easy
to implement, since the memory of the computer is also organized in a linear
fashion. Some commonly used linear data structures are arrays, linked lists, stacks
and queues.
In nonlinear data structures, data elements are not organized in a sequential
fashion. Data structures like multidimensional arrays, trees, graphs, tables and sets
are some examples of widely used nonlinear data structures.
Linear Data Structures:

Array:
An array is a collection of variables of the same type that are referred to through a common
name.
Operations on arrays are searching, insertion, deletion of an element.

Linked list:
linked list is a linear data structure which consist a group of nodes together represent a
sequence.
Each node is composed of data and an address (in other words, a link) to the next node in the
sequence.
The basic operations in a single linked list are:
Creation.
Insertion.
Deletion.
Traversing.
Stack:
A stack is a list of elements in which an element may be inserted or
deleted only at one end, called the top of the stack.

Stacks are sometimes known as LIFO (last in, first out) lists. i.e. the last
item to be added to a stack is the first item to be removed.

The two basic operations associated with stacks are:


1. Push: is the term used to insert an element into a stack.
2. Pop: is the term used to delete an element from a stack.
Queue:
Queue is a linear data structure, in which the first element is inserted from
one end called REAR(also called tail), and the deletion of exisiting element
takes place from the other end called as FRONT(also called head). This
makes queue as FIFO data structure, which means that element inserted first
will also be removed first.

The following operations on queues are:


enqueue: The process of adding an element at the end of the queue is
called Enqueue.
dequeue: The process of removing an element at the front of the queue is
called Dequeue.
Non Linear Data Structures:

Tree:
A tree is hierarchical collection of nodes. One of the nodes, known as the root, is
at the top of the hierarchy. Each node can have at most one link coming into it.
The node where the link originates is called the parent node. The root node has
no parent. The links leaving a node (any number of links are allowed) point to
child nodes. Trees are recursive structures. Each child node is itself the root of a
subtree. At the bottom of the tree are leaf nodes, which have no children.

Graph:
Graph G is a pair (V, E), where V is a finite set of vertices and E is a finite set of
edges.
A graph is generally displayed by following figure, in which the vertices are
represented by circles and the edges by lines.
Operations:

Traversal: accessing each node/element exactly once in the list.


(This accessing and processing is sometimes called “visiting” the node
or element.).
Inserting: Adding a new node/element to the data structure.
Deleting: Removing a node/element from the data structure.
Searching: Finding the location of the desired node/element in the
data structure.
Arrays:
An array is a collection of variables of the same type that are referred to through a
common name.
A specific element in an array is accessed by an index.
In C, all arrays consist of contiguous Memory locations. The lowest address corresponds
to the first element and the highest address to the last element.
The most common array is the string, which is simply an array of characters terminated
by a null.
Arrays can have from one to several dimensions.

Types of Array:-
i. One-dimensional arrays
ii. Multi-dimensional arrays
a) Two-dimensional arrays b)Three-dimensional array and so on
One-Dimension Arrays:
A list of items can be given with one variable name using only one subscript and such a
variable is called a single-subscripted variable or a One-dimensional array.

The general form for declaring a single-dimension array is


type var_name[size];
Here, type declares the base type of the array, which is the type of each element in the array,
and size defines how many elements the array will hold.

Example: We want to represent a set of 5 numbers, declare the array of variable name ‘num’.
int num[5];
The computer reserves five storage locations as following.
Initializing Array:-

Syntax:- <datatype> < arrayname>[size]={list of values};


Example:- int num[5]={10,20,30,40,50};
Memory Map With One-Dimensional Array:

The amount of storage required to hold an array is directly related to its type and size. Size
of a single dimension array:
total bytes = sizeof(base type) × length of array;
Example: int num[5];
total bytes = 2 x 5 =10 bytes of memory is allocated to the variable ‘num’ at compile time.
OPERATIONS ON ARRAYS:
1. Retrieval of an element
2. Searching an element
3. Insertion of an element
4. Deletion of an element

Retrieval(Accessing) Elements of an Array:


To get or access an element from an array by using index or position is called retrieval of
an element. An element of an array is accessed by indexing the array name. This is done by
placing the index of the element within square brackets after the name of the array.
This index number specifies the element’s position in the array. Index number starts with 0.
Thus, num[2] is not the second element of the array, but it is the third.
Example:
Example:
void main()
{
int a[5]={10,20,3,15,25};
int i;
//retrieving first and fifth elements from array elements
printf(“first element =%d \n”,a[0]);
printf(“fifth element =%d \n”,a[4]);
//retrieving all the elements from array elements
for ( i = 0 ; i <5 ; i++ )
{
printf ( "%d \n", a[i] ) ;
}
}
Searching an element from an array:

The process of finding the location of a particular element in an array is called searching,
it is the method for finding a particular value in the list.

Type of searching:
1. Linear (sequential) search.
2. Binary search.

1. Linear search: linear search or sequential search is a method for finding a particular
value in a list that checks each element in sequence until the desired element is found or
the list is exhausted. The list need not be ordered.
Algorithm: Linear search()
Step-1: Read size of the array ‘N’.
Step-2: Read array elements A.
Step-3: Read the variable ‘element’ to search from the array.
Step-4: SET count=0
Step-5: SET i=0 (counter variable)
Step-6: REPEAT step-7 UNTIL i < num
Step-7: IF element = =A[i] THEN
Count =1
Step-8: SET i=i+1 (increment counter variable)
Step-9: IF count =1 THEN
PRINT “element found in the array”
ELSE PRINT “element not found in the array”
PROGRAM:
include <stdio.h> /* Linear search begins */
void main() for (i = 0; i < n ; i++)
{ {
int a[100]; if (element == a[i] )
int i, n, element, count = 0; {
printf("Enter the size of array \n"); count = 1;
scanf("%d", &n); break;
printf("Enter the array elements \n"); }
for (i = 0; i < n; i++) }
{ if (count == 1)
scanf("%d", &a[i]); printf("Element is present in the array\n");
} else
printf("Enter the element to be searched \n"); printf("Element is not present in the array\n")
scanf("%d", &element);
Output: Enter the value of num 5
Enter the elements one by one
456 78 90 40 100
Enter the element to be searched 70
Element is not present in the array

Binary Search:

• Binary Search is applied on the sorted array or list.


• In binary search, we first compare the value with the elements in the middle position of
the array. If the value is matched, then we return the value.
• If the value is less than the middle element, then it must lie in the lower half of the array
and if it's greater than the element then it must lie in the upper half of the array.
• We repeat this procedure on the lower (or upper) half of the array.
• Binary Search is useful when there are large numbers of elements in an array
#include <stdio.h>
int main()
{
int i, first, last, middle, n, search, a[100];
printf("Enter number of elements\n");
scanf("%d",&n);
printf("Enter %d integers\n", n);
for (i = 0; c < n; i++)
scanf("%d“,&a[c]);
printf("Enter value to find\n");
scanf("%d", &search);
first = 0;
last = n - 1;
middle = (first+last)/2;
while (first <= last)
{
if (a[middle] < search)
first = middle + 1;
else if (a[middle] == search)
{
printf("%d found at location %d.\n", search, middle+1);
break;
}
else
last = middle - 1;
middle = (first + last)/2;
}
if (first > last)
printf("Not found! %d is not present in the list.\n",search);
return 0;
}
Insertion of an element:

Adding an element to an array is called insertion

Algorithm: INSERTION( )
step-1: Read size of the array ‘N’.
Step-2: Read array elements A.
FOR i=0 to N
Read A[i]
Step-3: Read the variable ‘element’ to insert in to the array.
Step-4: Read the variable ‘pos’ (‘pos’ is the position at which the element is to be inserted)
Step-5: SET i=n-1 (counter variable)
Step-6: REPEAT step-7 UNTIL i > pos-1
Step-7: A[i+1] = A[i];
Step-8: SET i=i-1 (decrement counter variable)
Step-9: PRINT “The resultant Array”
FOR i=0 to N
PRINT A[i]

Program:
#include <stdio.h>
void main()
{
int a[100], pos, i, n, value;
printf("Enter number of elements in array\n");
scanf("%d", &n);
printf("Enter the elements of the array\n", n);
for (i = 0; i< n; i++)
scanf("%d", &a[i]);
printf("Enter the location where you wish to insert an element\n");
scanf("%d", &pos);
printf("Enter the value to insert\n");
scanf("%d", &value);
for (i = n - 1; i >= pos - 1; i--)
a[i+1] = a[i];
a[pos-1] = value;
n=n+1;
printf("Resultant array after insertion is\n");
for (i = 0; i<= n; i++)
printf("%d\n", a[i]);
}
Output of program:
Enter number of elements in array Resultant array after insertion is
5 20
Enter the elements of the array 30
20 100
30 40
40 34
34 15
15
Enter the location where you wish to
insert an element
3
Enter the value to insert
100
Deletion of an element:

Deleting the value of an element from the array by using index position or key value is
called deletion of an element.

Algorithm: DELETION( )
Step-1: Read size of the array ‘N’.
Step-2: Read array elements A.
FOR i=0 to N
Read A[i]
Step-3: Read the variable ‘pos’ ( ‘pos’ is the position at which the element is to insert).
Step-4: IF pos > n+1 THEN PRINT “Deletion is not possible” exit(0).
Step-5: SET i=pos-1 (counter variable)
Step-6: REPEAT step-7 UNTIL i < n-1
Step-7: A[i] = A[i+1];
Step-8: SET i=i+1 (decrement counter variable)
Step-9: SET n=n-1
Step-10: PRINT “The resultant Array”
FOR i=0 to n
PRINT A[i]

Two-Dimensional Arrays:

A two -dimensional array is called an “array of one-dimensional arrays”.


Two-dimensional array is a type of array, which has finite number of rows and finite
number of columns.
The declaration form of 2-dimensional array is

Data_type Array_name [row size][column size];

The type may be any valid type supported by C.


The rule for giving the array_name is same as the ordinary variable.
The row size and column size should specify the number of rows and columns in an array.

Example: int arr[3][3];


The amount of memory allocated for 2D array in memory:
bytes = size of 1st index × size of 2nd index × sizeof(base type)

Example: Assuming 16-bit processor i.e. 2-byte for integers


int d[10][20];
memory = 10 x 20 x 2= 400 bytes allocated.
initializing two-dimensional array:
int anArray[3][3] = { { 10, 20, 4 5}, { 42, 79, 81}, { 89, 9, 36 } };
Reading & writing an 2D Array elements:
#include<stdio.h>
#include<conio.h>
void main()
{
int i, j;
int a[3][3];
printf(" reading 2D Array Elements from key board \n");
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%d",&a[i][j]);
}
}
printf(" writing 2D Array Elements on to the screen \n");
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
printf("%d\t",a[i][j]);
}
printf("\n");
}
}
Output: reading 2D Array Elements from key board
12 45 63 89 34 73 19 76 49
writing 2D Array Elements on to the screen

12 45 63
89 34 73
19 76 49
Linked List:

• A linked list is a linear collection of elements called nodes. Each node


consists two parts – the data part pointer part (pointer part stores the
address of next node).

• Linked list is a dynamic data structure.

• The data items in the linked list are not in consecutive memory
locations. They may be anywhere, but the accessing of these data
items is easier as each data item contains the address of the next data
item.
Advantages of linked lists:
Linked lists have many advantages. Some of the very important
advantages are:
1. Linked lists are dynamic data structures. i.e., they can grow or shrink
during the execution of a program.
2. Linked lists have efficient memory utilization. Here, memory is not
pre-allocated. Memory is allocated whenever it is required and it is de-
allocated (removed) when it is no longer needed.
3. Insertion and Deletions are easier and efficient. Linked lists provide
flexibility in inserting a data item at a specified position and deletion of
the data item from the given position.
4. Many complex applications can be easily carried out with linked lists.
Disadvantages of linked lists:
1. It consumes more space because every node requires a additional pointer
to store address of the next node.
2. Searching a particular element in list is difficult and also time consuming.

Types of Linked Lists:


1. Single Linked List.
2. Double Linked List.
3. Circular Linked List.
Single Linked List:

A single linked list is one in which all nodes are linked together in some
sequential manner. Hence, it is also called as linear linked list.
• A linked list allocates space for each element separately in its own block
of memory called a "node".
• Each node contains two fields; a "data" field to store whatever element,
and a "next" field which is a pointer used to link to the next node.
• Each node is allocated in the heap using malloc(), so the node memory
continues to exist until it is explicitly de-allocated using free().
• In single linked list, the beginning of the linked list is stored in a "start"
pointer which points to the first node. The first node contains a pointer to
the second node. The second node contains a pointer to the third node, ...
and so on. The last node in the list has its next field set to NULL to mark
the end of the list.
• Code can access any node in the list by starting at the start and following
the next pointers.
Implementation of Single Linked List:

Node structure:
Each node contains two fields; a "data" field to store data, and a "next" field
which is a pointer used to store the address of next node.

➢ Creating a structure with one data item and a next pointer, which will be
pointing to next node of the list. This is called as self-referential structure.
➢ Initialise the start pointer to be NULL.
struct node
{
int data;
struct node *next;
};
typedef struct node node;
node *start = NULL;

Creating a node for Single Linked List:

• Creating a singly linked list starts with creating a node. Sufficient memory has to be
allocated for creating a node.
• The information is stored in the memory, allocated by using the malloc() function.
• The function getnode(), is used for creating a node, after allocating memory for the
structure of type node, the information for the item (i.e., data) has to be read from the
user, set next field to NULL and finally returns the address of the node.
getnode ( ) function:

node* getnode()
{
node * newnode;
newnode = (node *) malloc(sizeof(node));
printf("\n Enter data: ");
scanf("%d", &newnode -> data);
newnode -> next = NULL;
return newnode;
}
Creating a Single Linked List with ‘n’ number of nodes:
Insertion of a Node:
The new node can then be inserted at three different places namely:
a. Inserting a node at the beginning.
b. Inserting a node at the end.
c. Inserting a node at intermediate position.

Inserting a node at the beginning:


The following steps are to be followed to insert a new node at the beginning
of the list:
1. Get the new node using getnode().
newnode = getnode();
2. If the list is empty then start = newnode.
3. If the list is not empty, follow the steps given below:
newnode -> next = start;
start = newnode;
Insert node at position:
The following steps are followed, to insert a new node in an intermediate position in the
list:
1. Get the new node using getnode().
newnode = getnode();
2. Read the position ‘pos’
3. Store the starting address (which is in start pointer) in temp pointer. Then traverse the
temp pointer upto the specified position.
temp =start;
for(i=1; i<pos-1; i++)
{
temp = temp -> next;
}
4. After reaching the specified position, follow the steps given below:
newnode -> next = temp -> next;
temp -> next = newnode;
Deletion of a node:

Another primitive operation that can be done in a single linked list is the
deletion of a node.

Memory is to be released for the node to be deleted. A node can be deleted


from the list from three different places namely.
a. Deleting a node at the beginning.
b. Deleting a node at the end.
c. Deleting a node at intermediate position.
Deleting a node at the beginning:

The following steps are followed, to delete a node at the beginning of the list:

1. If list is empty then display ‘Empty List’ message.


IF start == NULL THEN
printf("\n Empty List’..");

2. If the list is not empty, follow the steps given below:


temp = start;
start = start -> next;
free(temp);
Deleting a node at the end:
The following steps are followed to delete a node at the end of the list:
1. If list is empty then display ‘Empty List’ message.
2. If the list is not empty, follow the steps given below:
temp = prev = start;
while(temp -> next != NULL)
{
prev=temp;
temp = temp -> next;
}
prev -> next = NULL;
free(temp);
Deleting a node at Intermediate position:
The following steps are followed, to delete a node from an intermediate position in the
list (List must contain more than two node).
1. If list is empty then display ‘Empty List’ message
2. If the list is not empty, follow the steps given below.
for(i=1;i<pos;i++)
{
prev = temp;
temp = temp -> next;
}
prev -> next = temp -> next;
free(temp);
printf("\n Node deleted..");
Traversal and displaying a list (Left to Right):

To display the information, you have to traverse (move) a linked list,


node by node from the first node, until the end of the list is reached.

Traversing a list involves the following steps:


Assign the address of start pointer to a temp pointer.
temp = start;
Display the information from the data field of each node.
while (temp != NULL)
{
printf("%d ->", temp -> data);
temp = temp -> next;
}
Double Linked List:

A double linked list is a two-way list in which all nodes will have two links.
This helps in accessing both successor node and predecessor node from the
given node position.

Each node in a double linked list has two link fields (pointers) to point to the
left node (previous) and the right node (next). This helps to traverse in
forward direction and backward direction.

Thus it can be said that it provides bi-directional traversing.


Each node contains three fields:
Left link.
Data.
Right link.
Creating a node for Double Linked List:
Creating a double linked list starts with creating a node. Sufficient memory
has to be allocated for creating a node.
The memory is allocated by using the malloc() function.
Creating a Double Linked List with ‘n’ number of nodes:

The following steps are to be followed to create ‘n’ number of nodes:


1. Get the new node using getnode().
newnode =getnode();
2. If the list is empty then start = newnode.
3. If the list is not empty, follow the steps given below:
The left field of the new node is made to point the previous node.
The previous nodes right field must be assigned with address of the new
node.
4. Repeat the above steps ‘n’ times.
Inserting a node at the beginning:

The following steps are to be followed to insert a new node at the beginning
of the list:
1. Get the new node using getnode().
newnode=getnode();
2. If the list is empty then start = newnode.
3. If the list is not empty, follow the steps given below:
newnode -> right = start;
start -> left = newnode;
start = newnode;
Inserting a node at the end:
The following steps are followed to insert a new node at the end of the
list:
1. Get the new node using getnode()
newnode=getnode();
2. If the list is empty then start = newnode.
3. If the list is not empty follow the steps given below:
temp = start;
while(temp -> right != NULL)
temp = temp -> right;
temp -> right = newnode;
newnode -> left = temp;
Inserting a node at an intermediate position:

The following steps are followed, to insert a new node in an intermediate position in the list:
1. Get the new node using getnode().
newnode=getnode();
2. Read the position at which do you want to insert- ‘pos’
3. Store the starting address (which is in start pointer) in ‘temp’ and ‘prev’ pointers.
temp=start;
prev=start;
4. Traverse the temp pointer upto the specified position followed by prev pointer.
5. After reaching the specified position, follow the steps given below:
newnode -> left = temp;
newnode -> right = temp -> right;
temp -> right -> left = newnode;
temp -> right = newnode;
Deleting a node at the beginning:

The following steps are followed, to delete a node at the beginning of the list:
1. If list is empty then display ‘Empty List’ message.
2. If the list is not empty, follow the steps given below:
temp = start;
start = start -> right;
start -> left = NULL;
free(temp);
Deleting a node at the end:
The following steps are followed to delete a node at the end of the list:
1. If list is empty then display ‘Empty List’ message
2. If the list is not empty, follow the steps given below:
temp = start;
while(temp -> right != NULL)
{
temp = temp -> right;
}
temp -> left -> right = NULL;
free(temp);
Deleting a node at Intermediate position:
void dll_delete_mid()
else
{ {
int i , pos; printf("\n Enter the position of the node
node *temp; to delete: ");
if(start == NULL) scanf("%d", &pos);
{ temp=start;
prev=start;
printf("\n Empty List"); for(i=1;i<pos;i++)
} {
prev = temp;
temp =temp -> right;
}
prev -> right = temp -> right;
temp -> right -> left = prev;
free(temp);
printf("\n node deleted..");
}
}
Traversal and displaying a list (Left to Right):
To display the information, you have to traverse the list, node by node from the first
node, until the end of the list is reached. The function traverse_left_right() is used for
traversing and displaying the information stored in the list from left to right.

The following steps are followed, to traverse a list from left to right:
1. If list is empty then display ‘Empty List’ message.
2. If the list is not empty, follow the steps given below:
temp = start;
while(temp != NULL)
{
Print temp-> data;
temp = temp -> right;
}
Circular linked list
• A single linked list can be made a circular linked list by simply storing
address of the very first node in the link field of the last node.
• A circular linked list has no beginning and no end. It is necessary to
establish a special pointer called start pointer always pointing to the first
node of the list.
• In circular linked list no null pointers are used, hence all pointers contain
valid address.
Creating a circular single Linked List with ‘n’ number of nodes:

The following steps are to be followed to create ‘n’ number of nodes:


1. Get the new node using getnode().
newnode = getnode();
2. If the list is empty, assign new node as start.
start = newnode;
3. If the list is not empty, follow the steps given below:
temp = start;
while(temp -> next != NULL)
temp = temp -> next;
temp -> next = newnode;
4. Repeat the above steps ‘n’ times.
5. newnode -> next = start;
Inserting a node at the beginning:

The following steps are to be followed to insert a new node at the beginning of the
circular list:
1. Get the new node using getnode().
newnode = getnode();
2. If the list is empty, assign new node as start.
start = newnode;
newnode -> next = start;
3. If the list is not empty, follow the steps given below:
temp = start;
while(temp -> next != start)
temp= temp -> next;
newnode -> next = start;
start = newnode;
temp -> next = start;
Figure shows inserting a node into the circular single linked list at the beginning
void cll_insert_beg()
{ {
node *newnode, *temp; temp = start;
newnode = getnode(); while(temp -> next != start)
if(start == NULL) temp= temp -> next;
{ newnode -> next = start;
start = newnode; start = newnode;
newnode -> next = start; temp -> next = start;
} }
else }
Inserting a node at the end:

The following steps are followed to insert a new node at the end of the list:
1. Get the new node using getnode().
newnode = getnode();
2. If the list is empty, assign new node as start.
start = newnode;
newnode -> next = start;
3. If the list is not empty follow the steps given below:
temp = start;
while(temp -> next != start)
temp = temp -> next;
temp -> next = newnode;
newnode -> next = start;
Figure shows inserting a node into the circular single linked list at the end.
Insert node at a position:
The following steps are followed, to insert a new node in an intermediate
position in the list:
1. Get the new node using getnode().
newnode = getnode();
2. Read the position ‘pos’
3. Store the starting address (which is in start pointer) in temp pointer. Then
traverse the temp pointer upto the specified position.
temp =start;
for(i=1; i<pos-1; i++)
{
temp = temp -> next;
}
4. After reaching the specified position, follow the steps given below:
newnode -> next = temp -> next;
temp -> next = newnode;
Deleting a node at the beginning:

The following steps are followed, to delete a node at the beginning of the list:
1. If the list is empty, display a message ‘Empty List’.
2. If the list is not empty, follow the steps given below:
last = temp = start;
while(last -> next != start)
{ last= last -> next; }
start = start -> next;
last -> next = start;
free(temp)
3. After deleting the node, if the list is empty then start = NULL.

[before deleting check if(start->next==NULL) that is list contains only one node. And
after deleting that node list becomes empty. That is start =NULL]
Figure shows deleting a node at the beginning of a circular single linked list.
Deleting a node at the end:

The following steps are followed to delete a node at the end of the list:
1. If the list is empty, display a message ‘Empty List’.
2. If the list is not empty, follow the steps given below:
temp = start;
prev = start;
while(temp -> next != start)
{
prev=temp;
temp = temp -> next;
}
prev -> next = start;
3. After deleting the node, if the list is empty then start = NULL.
Figure shows deleting a node at the end of a circular single linked list.
Deleting a node at Intermediate position:

The following steps are followed, to delete a node from an intermediate position in the
list (List must contain more than two node).
1. If list is empty then display ‘Empty List’ message
2. If the list is not empty, follow the steps given below.
for(i=1;i<pos;i++)
{
prev = temp;
temp = temp -> next;
}
prev -> next = temp -> next;
free(temp);
printf("\n Node deleted..");
void delete_mid()
{ {
int i, pos; printf("\n Enter position of node to
node *temp, *prev; delete: ");
if(start == NULL) scanf("%d", &pos);
{ temp = prev = start;
printf("\n Empty List.."); for(i=1;i<pos;i++)
return ; {
} prev = temp;
else temp = temp -> next;
}
prev -> next = temp -> next;
free(temp);
printf("\n Node deleted..");
}
}
Traversing a circular single linked list from left to right:

The following steps are followed, to traverse a list from left to right:
1. If list is empty then display ‘Empty List’ message.
2. If the list is not empty, follow the steps given below:
temp = start;
do
{
printf("%d", temp -> data);
temp = temp -> next;
} while(temp != start);
Algorithm:
An algorithm is a well-defined sequence of instructions designed to perform a specific task
or solve a particular problem. It is a step-by-step procedure that takes an input, processes it
through a series of operations, and produces an output.
Characteristics of an Algorithm:
1.Finite: An algorithm must always terminate after a finite number of steps. It should not
run indefinitely.
2.Definite: Each step of the algorithm must be precisely defined and unambiguous. The
actions to be performed in each step should be clear.
3.Input: An algorithm has zero or more inputs, taken from a specified set of objects.
4.Output: An algorithm has one or more outputs, which are the results of the computations.
5.Effectiveness: The steps of the algorithm must be basic enough that they can be carried
out, in principle, by a person using a pen and paper.
6.Deterministic: For a given input, the algorithm should produce the same output every
time it is run.
7.General: The algorithm should be applicable to a class of problems rather than a single
specific problem.
Asymptotic Analysis:
➢ Asymptotic analysis is used to measure efficiency of algorithm.
➢ The efficiency of an algorithm depends on the amount of time,
storage and other resources required to execute the algorithm.
➢ The efficiency is measured with the help of asymptotic
notations.
➢ An algorithm may not have the same performance for different
types of inputs. With the increase in the input size, the
performance will change.
Asymptotic Notations

➢ Asymptotic notations are the mathematical notations used to


describe the running time of an algorithm.
➢ For example: In bubble sort, when the input array is already
sorted, the time taken by the algorithm is linear i.e. the best case.
➢ But, when the input array is in reverse condition, the algorithm
takes the maximum time (quadratic) to sort the elements i.e. the
worst case.
➢ When the input array is neither sorted nor in reverse order, then
it takes average time.
➢ These durations are denoted using asymptotic notations.
There are mainly three asymptotic notations:
•Big-O notation
•Omega notation
•Theta notation
Big-O Notation (O-notation)
• Big-O notation represents the upper bound of the
running time of an algorithm.
• Thus, it gives the worst-case complexity of an
algorithm.
o The below expression can be described as a function f(n) belongs
to the set O(g(n)) if there exists a positive constant c
such that it lies between 0 and cg(n), for sufficiently large n.

• For any value of n, the running time of an algorithm does not


cross the time provided by O(g(n)).
Since it gives the worst-case running time of an algorithm, it is
widely used to analyze an algorithm as we are always interested in
the worst-case scenario.

O(g(n)) = { f(n): there exist positive constants c and n0


such that 0 ≤ f(n) ≤ cg(n) for all n ≥ n0 }
Omega Notation (Ω-notation)
Omega notation represents the lower bound of the running time of an
algorithm. Thus, it provides the best case complexity of an algorithm.
Ω(g(n)) = { f(n): there exist positive constants c and n0 such that
0 ≤ cg(n) ≤ f(n) for all n ≥ n0 }

The above expression can be described as a function f(n) belongs to the


set Ω(g(n)) if there exists a positive constant c such that it lies above cg(n), for
sufficiently large n.
For any value of n, the minimum time required by the algorithm is given by
Omega Ω(g(n)).
Theta Notation (Θ-notation)
Theta notation encloses the function from above
and below. Since it represents the upper and the lower
bound of the running time of an algorithm, it is used for
analyzing the average-case complexity of an algorithm.
Θ(g(n)) = { f(n): there exist positive constants c1, c2 and n0
such that 0 ≤ c1g(n) ≤ f(n) ≤ c2g(n) for all n ≥ n0 }

The above expression can be described as a function f(n) belongs to the


set Θ(g(n)) if there exist positive constants c1

and c such that it can be sandwiched between c g(n) and c g(n), for sufficiently large n.
2 1 2

If a function f(n) lies anywhere in between c g(n) and c g(n) for all n ≥ n0, then f(n) is said
1 2

to be asymptotically tight bound.


Algorithm Complexity

• Suppose X is treated as an algorithm and N is treated as the size


of input data, the time and space implemented by the Algorithm X
are the two main factors which determine the efficiency of X.

• Time Factor − The time is calculated or measured by counting the


number of key operations such as comparisons in sorting
algorithm.

• Space Factor − The space is calculated or measured by counting


the maximum memory space required by the algorithm.
The complexity of an algorithm f(N) provides the running time and /
or storage space needed by the algorithm with respect of N as the
size of input data.
Space Complexity
Space complexity of an algorithm represents the amount of memory
space needed the algorithm in its life cycle.
Space needed by an algorithm is equal to the sum of the following
two components
✓ A fixed part that is a space required to store certain data and
variables (i.e. simple variables and constants, program size etc.),
that are not dependent of the size of the problem.

✓ A variable part is a space required by variables, whose size is


totally dependent on the size of the problem. For example,
recursion stack space, dynamic memory allocation etc.

✓ Space complexity S(p) of any algorithm p is S(p) = A + Sp(I) Where


A is treated as the fixed part and S(I) is treated as the variable part
of the algorithm which depends on instance characteristic I.
Following is a simple example that tries to explain the concept
SUM(P, Q)
Step 1 – START
Step 2 - R ← P + Q + 10
Step 3 - Stop

Here we have three variables P, Q and R and one


constant. Hence S(p) = 1+3. Now space is
dependent on data types of given constant types
and variables and it will be multiplied accordingly.
Time Complexity
❖ Time Complexity of an algorithm is the representation of
the amount of time required by the algorithm to execute
to completion.
❖ Time requirements can be denoted or defined as a
numerical function t(N), where t(N) can be measured as
the number of steps, provided each step takes constant
time.
❖ For example, in case of addition of two n-bit integers, N
steps are taken. Consequently, the total computational
time is t(N) = c*n, where c is the time consumed for
addition of two bits. Here, we observe that t(N) grows
linearly as input size increases.

You might also like