122ax042 DS 6-10

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 40

NAME:

BATCH: B
BRANCH: CSE IOT
PRN: 122AX0
Experiment No. 6

AIM: To Study and Implement Circular Queue


A Circular Queue is an extended version of a normal queue where the
last element of the queue is connected to the first element of the queue
forming a circle.
The operations are performed based on FIFO (First In First Out)
principle. It is also called ‘Ring Buffer’.

In a normal Queue, we can insert elements until queue becomes full.


But once queue becomes full, we can not insert the next element even
if there is a space in front of queue.
Operations on Circular Queue:
 Front: Get the front item from the queue.

 Rear: Get the last item from the queue.

 enQueue(value) This function is used to insert an element into


the circular queue. In a circular queue, the new element is
always inserted at the rear position.
o Check whether the queue is full – [i.e., the rear end is in
just before the front end in a circular manner].
o If it is full then display Queue is full.
 If the queue is not full then, insert an element at the
end of the queue.

 deQueue() This function is used to delete an element from the


circular queue. In a circular queue, the element is always deleted
from the front position.
o Check whether the queue is Empty.
o If it is empty then display Queue is empty.
 If the queue is not empty, then get the last element
and remove it from the queue.

Illustration of Circular Queue Operations:

Implement Circular Queue using Array:


1. Initialize an array queue of size n, where n is the maximum
number of elements that the queue can hold.

2. Initialize two variables front and rear to -1.


3. Enqueue: To enqueue an element x into the queue, do the
following:
o Increment rear by 1.
 If rear is equal to n, set rear to 0.
o If front is -1, set front to 0.
o Set queue[rear] to x.

4. Dequeue: To dequeue an element from the queue, do the


following:
o Check if the queue is empty by checking if front is -1.
 If it is, return an error message indicating that the
queue is empty.
o Set x to queue[front].
o If front is equal to rear, set front and rear to -1.
o Otherwise, increment front by 1 and if front is equal to n,
set front to 0.
o Return x.
OUTPUT:
Conclusion: Through this experiment we have understood the
implementation of Circular Queue.
Experiment No. 7

AIM: To Study and Implement Linked List


Linked List is a linear data structure, in which elements are not stored
at a contiguous location, rather they are linked using pointers. Linked
List forms a series of connected nodes, where each node stores the
data and the address of the next node.

What is Linked List

Node Structure: A node in a linked list typically consists of two


components:
Data: It holds the actual value or data associated with the node.
Next Pointer: It stores the memory address (reference) of the next
node in the sequence.
Head and Tail: The linked list is accessed through the head node,
which points to the first node in the list. The last node in the list
points to NULL or nullptr, indicating the end of the list. This node is
known as the tail node.
Why linked list data structure needed?
Here are a few advantages of a linked list that is listed below, it will
help you understand why it is necessary to know.

Dynamic Data structure: The size of memory can be allocated or de-


allocated at run time based on the operation insertion or deletion.
Ease of Insertion/Deletion: The insertion and deletion of elements are
simpler than arrays since no elements need to be shifted after insertion
and deletion, Just the address needed to be updated.
Efficient Memory Utilization: As we know Linked List is a dynamic
data structure the size increases or decreases as per the requirement so
this avoids the wastage of memory.
Implementation: Various advanced data structures can be
implemented using a linked list like a stack, queue, graph, hash maps,
etc.
Single-linked list:
In a singly linked list, each node contains a reference to the next node
in the sequence. Traversing a singly linked list is done in a forward
direction.

Single-linked list
In a singly linked list, each node contains a reference to the next node
in the sequence. Traversing a singly linked list is done in a forward
direction.
OUTPUT:
Conclusion: Through this experiment we have understood the
implementation of Linked List.
Experiment No. 8

AIM: To Study and Implement Circular Linked List

The circular linked list is a linked list where all nodes are connected
to form a circle. In a circular linked list, the first node and the last
node are connected to each other which forms a circle. There is no
NULL at the end.

Circular singly linked list: In a circular Singly linked list, the last
node of the list contains a pointer to the first node of the list. We
traverse the circular singly linked list until we reach the same node
where we started. The circular singly linked list has no beginning or
end. No null value is present in the next part of any of the nodes.

Operations on the circular linked list:


We can do some operations on the circular linked list similar to the
singly linked list which are:
1. Insertion
2. Deletion

1. Insertion in the circular linked list:


A node can be added in three ways:
1. Insertion at the beginning of the list
2. Insertion at the end of the list
3. Insertion in between the nodes
1) Insertion at the beginning of the list: To insert a node at the
beginning of the list, follow these steps:
 Create a node, say T.
 Make T -> next = last -> next.
 last -> next = T.

And then,

2) Insertion at the end of the list: To insert a node at the end of the
list, follow these steps:
 Create a node, say T.
 Make T -> next = last ->next;
 last -> next = T.
 last = T.

Before insertion,
After insertion,

3) Insertion in between the nodes: To insert a node in between the


two nodes, follow these steps:
 Create a node, say T.
 Search for the node after which T needs to be inserted, say that
node is P.
 Make T -> next = P ->next;
 P -> next = T.

Suppose 12 needs to be inserted after the node has the value 10,
After searching and insertion,

2. Deletion in a circular linked list:


1) Delete the node only if it is the only node in the circular linked
list:
 Free the node’s memory
 The last value should be NULL A node always points to another
node, so NULL assignment is not necessary.
Any node can be set as the starting point.
Nodes are traversed quickly from the first to the last.
2) Deletion of the last node:
 Locate the node before the last node (let it be temp)
 Keep the address of the node next to the last node in temp
 Delete the last memory
 Put temp at the end

3) Delete any node from the circular linked list: We will be given a
node and our task is to delete that node from the circular linked list.
Algorithm:
Case 1: List is empty.
 If the list is empty we will simply return.

Case 2:List is not empty


 If the list is not empty then we define two pointers currand prev
and initialize the pointer curr with the head node.
 Traverse the list using curr to find the node to be deleted and
before moving to curr to the next node, every time set prev =
curr.
 If the node is found, check if it is the only node in the list. If yes,
set head = NULL and free(curr).
 If the list has more than one node, check if it is the first node of
the list. Condition to check this( curr == head). If yes, then
move prev until it reaches the last node. After prev reaches the
last node, set head = head -> next and prev -> next = head.
Delete curr.
 If curr is not the first node, we check if it is the last node in the
list. Condition to check this is (curr -> next == head).
 If curr is the last node. Set prev -> next = head and delete the
node curr by free(curr).
 If the node to be deleted is neither the first node nor the last
node, then set prev -> next = curr -> next and delete curr.
 If the node is not present in the list return head and don’t do
anything.
OUTPUT:

Conclusion: Through this experiment we have understood the


implementation of Circular Linked List.
Experiment No. 9

Aim: To Study and Implement Binary Search Tree


This article explains the many operations of a binary search tree
application that has been coded in the C programming language. A
binary search tree is a binary tree where each node's left subtree value
is less than the node's value, which is less than each value in the right
subtree.
In this article, we'll define a binary search tree and show you how to
use the C programming language to accomplish various binary search
tree operations.
A specific type of data structure called a tree is used to represent data
in a hierarchical format. It can be described as a group of nodes-
collections of things or entities-that are connected to one another to
create the illusion of a hierarchy. Trees are non-linear data structures
because their data is not organised in a linear or sequential manner.
The items are arranged in a binary search tree according to a certain
order. A Binary search tree requires that the left node's value be less
than the parent node and the right node's value be larger than the
parent node. The left and right branches of the root are subject to this
rule in a recursive fashion.
It is advised to first see a quick explanation of the Tree data structure
before moving on to the binary search tree.
Basics of the Binary Search Tree in C
A binary search tree is a type of tree data structure that enables users
to sort and store information. Because each node can only have two
children, it is known as a binary tree. It is also known as a search tree
because we can look up numbers in O(log(n)) time.
Typical characteristics of a binary tree are:
o The root node is greater than all nodes in the left subtree.

o The root node is outperformed in value by every node in the


right subtree.
o Each node's two subtrees are likewise binary search trees,
therefore they have the aforementioned two characteristics.
Binary Search Tree Example
The diagram below shows two binary search trees, one of which
complies with all of the requirements for a binary search tree while
the other deviates from the standard.

The right subtree of node 3 includes a value less than it, hence the
binary tree on the right isn't a binary search tree.
How to Operate a Binary Search Tree in C
A binary search tree can be processed using three fundamental
operations:
Operation 1: Search
We need to locate a particular piece in the data structure in Search.
Because the elements are stored in sorted order in binary search trees,
the searching process is made simpler.
The following is the algorithm for seeking an element in a binary tree:
1. Compare the searchable element to the tree's root node.
2. Return the root node if the value of the element being searched
matches the value of the root node.
3. If the value is not the same, see if it is smaller than the root
element, and if so, navigate to the left subtree.
4. Explore the appropriate subtree if it is greater than the root
element.
5. Return NULL if the element isn't present throughout the entire
tree.
With the aid of an example where we are attempting to search for an
item having a value of 20, let's now explore search operation in a
binary search tree code written in C:
Step 1:

Step 2:

Step 2:
Operation 2: Insert
In a binary search tree, an element is always inserted at the leaf node.
If the element to be inserted is smaller than the root value or the root
node, we start our search operation from the root node and look for an
empty position in the left subtree; otherwise, we look for the empty
location in the right subtree.
The following is the algorithm for adding an element to a binary tree:
C Code:
1. if node == NULL
2. return creatingNode(data)
3. if (data < node -> data)
4. node -> left = insert(node -> left, data)
5. else if (data > node -> data)
6. node -> right = insert(node -> right, data)
7. return node
Now that we have a specific instance where we are trying to insert an
item with the value 65, let's examine how insertion works in a binary
search tree:
Operation 3: Deletion
A node from the binary search tree must be deleted during the
deletion operation without violating any of its attributes. Deletion
may happen in one of three situations:
1. Leaf node is the first node to be eliminated.
The simplest scenario for removing a node from a binary search tree
is this one. Here, we'll swap out the leaf node for NULL and release
the space that was allotted.
With the aid of an example that shows us to delete the node with a
value of 90, we can better comprehend the deletion process in a
binary search tree.
2. The deleted node has just one child node.
In this instance, the target node will be replaced with its child, which
will then be deleted. As a result, the value to be erased will now be
present in the child node. Therefore, to release the space allotted, we
will simply replace the child node with NULL.
In the example below, a node with a value of 79 must be eliminated.
Since this node has just one child, 55 will be used in its place.

3. There are two children of the to-be-deleted node.


In comparison to the other two cases, this one is more complicated.
Here, we do the following actions to remove the node:
o We'll locate the target node's inorder successor so it can be
removed.
o Once the target node reaches the leaf, swap out this node for the
successor.
o NULL should be used in place of the target node to release the
designated space.
In the example below, the root node, node 45, must be deleted. As a
result, node 55 will be added in its place as the root node's immediate
successor. Node 45 will now be near the tree's leaf, making it simple
to delete.
OUTPUT:

Conclusion: Through this experiment we have understood the


implementation of Binary Search Tree.
Experiment No. 10

AIM: To Study and Implement Graph Traversal


DFS Algorithm
In this article, we will discuss the BFS algorithm in the data structure.
Breadth-first search is a graph traversal algorithm that starts
traversing the graph from the root node and explores all the
neighboring nodes. Then, it selects the nearest node and explores all
the unexplored nodes. While using BFS for traversal, any node in the
graph can be considered as the root node.
There are many ways to traverse the graph, but among them, BFS is
the most commonly used approach. It is a recursive algorithm to
search all the vertices of a tree or graph data structure. BFS puts every
vertex of the graph into two categories - visited and non-visited. It
selects a single node in a graph and, after that, visits all the nodes
adjacent to the selected node.
Applications of BFS algorithm
The applications of breadth-first-algorithm are given as follows -
o BFS can be used to find the neighboring locations from a given
source location.
o In a peer-to-peer network, BFS algorithm can be used as a
traversal method to find all the neighboring nodes. Most torrent
clients, such as BitTorrent, uTorrent, etc. employ this process to
find "seeds" and "peers" in the network.
o BFS can be used in web crawlers to create web page indexes. It
is one of the main algorithms that can be used to index web
pages. It starts traversing from the source page and follows the
links associated with the page. Here, every web page is
considered as a node in the graph.
o BFS is used to determine the shortest path and minimum
spanning tree.
o BFS is also used in Cheney's technique to duplicate the garbage
collection.
o It can be used in ford-Fulkerson method to compute the
maximum flow in a flow network.
Algorithm
The steps involved in the BFS algorithm to explore a graph are given
as follows -
Step 1: SET STATUS = 1 (ready state) for each node in G
Step 2: Enqueue the starting node A and set its STATUS = 2 (waiting
state)
Step 3: Repeat Steps 4 and 5 until QUEUE is empty
Step 4: Dequeue a node N. Process it and set its STATUS = 3
(processed state).
Step 5: Enqueue all the neighbours of N that are in the ready state
(whose STATUS = 1) and set
their STATUS = 2
(waiting state)
[END OF LOOP]
Step 6: EXIT
Example of BFS algorithm
Now, let's understand the working of BFS algorithm by using an
example. In the example given below, there is a directed graph having
7 vertices.

In the above graph, minimum path 'P' can be found by using the BFS
that will start from Node A and end at Node E. The algorithm uses
two queues, namely QUEUE1 and QUEUE2. QUEUE1 holds all the
nodes that are to be processed, while QUEUE2 holds all the nodes
that are processed and deleted from QUEUE1.
Now, let's start examining the graph starting from Node A.
Step 1 - First, add A to queue1 and NULL to queue2.
1. QUEUE1 = {A}
2. QUEUE2 = {NULL}
Step 2 - Now, delete node A from queue1 and add it into queue2.
Insert all neighbors of node A to queue1.
1. QUEUE1 = {B, D}
2. QUEUE2 = {A}
Step 3 - Now, delete node B from queue1 and add it into queue2.
Insert all neighbors of node B to queue1.
1. QUEUE1 = {D, C, F}
2. QUEUE2 = {A, B}
Step 4 - Now, delete node D from queue1 and add it into queue2.
Insert all neighbors of node D to queue1. The only neighbor of Node
D is F since it is already inserted, so it will not be inserted again.
1. QUEUE1 = {C, F}
2. QUEUE2 = {A, B, D}
Step 5 - Delete node C from queue1 and add it into queue2. Insert all
neighbors of node C to queue1.
1. QUEUE1 = {F, E, G}
2. QUEUE2 = {A, B, D, C}
Step 5 - Delete node F from queue1 and add it into queue2. Insert all
neighbors of node F to queue1. Since all the neighbors of node F are
already present, we will not insert them again.
1. QUEUE1 = {E, G}
2. QUEUE2 = {A, B, D, C, F}
Step 6 - Delete node E from queue1. Since all of its neighbors have
already been added, so we will not insert them again. Now, all the
nodes are visited, and the target node E is encountered into queue2.
1. QUEUE1 = {G}
2. QUEUE2 = {A, B, D, C, F, E}
Complexity of BFS algorithm
Time complexity of BFS depends upon the data structure used to
represent the graph. The time complexity of BFS algorithm
is O(V+E), since in the worst case, BFS algorithm explores every
node and edge. In a graph, the number of vertices is O(V), whereas
the number of edges is O(E).
The space complexity of BFS can be expressed as O(V), where V is
the number of vertices.’

DFS (Depth First Search) algorithm


In this article, we will discuss the DFS algorithm in the data structure.
It is a recursive algorithm to search all the vertices of a tree data
structure or a graph. The depth-first search (DFS) algorithm starts
with the initial node of graph G and goes deeper until we find the goal
node or the node with no children.
Because of the recursive nature, stack data structure can be used to
implement the DFS algorithm. The process of implementing the DFS
is similar to the BFS algorithm.
The step by step process to implement the DFS traversal is given as
follows -
1. First, create a stack with the total number of vertices in the
graph.
2. Now, choose any vertex as the starting point of traversal, and
push that vertex into the stack.
3. After that, push a non-visited vertex (adjacent to the vertex on
the top of the stack) to the top of the stack.
4. Now, repeat steps 3 and 4 until no vertices are left to visit from
the vertex on the stack's top.
5. If no vertex is left, go back and pop a vertex from the stack.
6. Repeat steps 2, 3, and 4 until the stack is empty.
Applications of DFS algorithm
The applications of using the DFS algorithm are given as follows -
o DFS algorithm can be used to implement the topological sorting.
o It can be used to find the paths between two vertices.

o It can also be used to detect cycles in the graph.

o DFS algorithm is also used for one solution puzzles.

o DFS is used to determine if a graph is bipartite or not.

Algorithm
Step 1: SET STATUS = 1 (ready state) for each node in G
Step 2: Push the starting node A on the stack and set its STATUS = 2
(waiting state)
Step 3: Repeat Steps 4 and 5 until STACK is empty
Step 4: Pop the top node N. Process it and set its STATUS = 3
(processed state)
Step 5: Push on the stack all the neighbors of N that are in the ready
state (whose STATUS = 1) and set their STATUS = 2 (waiting state)
[END OF LOOP]
Step 6: EXIT
Pseudocode
1. DFS(G,v) ( v is the vertex where the search starts )
2. Stack S := {}; ( start with an empty stack )
3. for each vertex u, set visited[u] := false;
4. push S, v;
5. while (S is not empty) do
6. u := pop S;
7. if (not visited[u]) then
8. visited[u] := true;
9. for each unvisited neighbour w of uu
10. push S, w;
11. end if
12. end while
13. END DFS()
Example of DFS algorithm
Now, let's understand the working of the DFS algorithm by using an
example. In the example given below, there is a directed graph having
7 vertices.
Now, let's start examining the graph starting from Node H.
Step 1 - First, push H onto the stack.
1. STACK: H
Step 2 - POP the top element from the stack, i.e., H, and print it. Now,
PUSH all the neighbors of H onto the stack that are in ready state.
1. Print: H]STACK: A
Step 3 - POP the top element from the stack, i.e., A, and print it. Now,
PUSH all the neighbors of A onto the stack that are in ready state.
1. Print: A
2. STACK: B, D
Step 4 - POP the top element from the stack, i.e., D, and print it. Now,
PUSH all the neighbors of D onto the stack that are in ready state.
1. Print: D
2. STACK: B, F
Step 5 - POP the top element from the stack, i.e., F, and print it. Now,
PUSH all the neighbors of F onto the stack that are in ready state.
1. Print: F
2. STACK: B
Step 6 - POP the top element from the stack, i.e., B, and print it. Now,
PUSH all the neighbors of B onto the stack that are in ready state.
1. Print: B
2. STACK: C
Step 7 - POP the top element from the stack, i.e., C, and print it. Now,
PUSH all the neighbors of C onto the stack that are in ready state.
1. Print: C
2. STACK: E, G
Step 8 - POP the top element from the stack, i.e., G and PUSH all the
neighbors of G onto the stack that are in ready state.
1. Print: G
2. STACK: E
Step 9 - POP the top element from the stack, i.e., E and PUSH all the
neighbors of E onto the stack that are in ready state.
1. Print: E
2. STACK:
Now, all the graph nodes have been traversed, and the stack is empty.
Complexity of Depth-first search algorithm
The time complexity of the DFS algorithm is O(V+E), where V is the
number of vertices and E is the number of edges in the graph.
The space complexity of the DFS algorithm is O(V).
BFS:

OUTPUT OF BFS :
DFS:
OUTPUT OF DFS:
Conclusion: Through this experiment we have understood the
implementation of Graph Traversal.

You might also like