Module 1_DSA
Module 1_DSA
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.
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:
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.
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:-
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
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:
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:
12 45 63
89 34 73
19 76 49
Linked List:
• 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.
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 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.
Another primitive operation that can be done in a single linked list is the
deletion of a node.
The following steps are followed, to delete a node at the beginning of the 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.
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 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
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