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

Algorithm: Sum and Average of Array Elements

The document outlines various algorithms for operations on arrays, strings, and linked lists, including calculating sums and averages, inserting and deleting elements, and reversing linked lists. It also explains memory representation for 2D arrays and sparse matrices, along with algorithms for checking if a matrix is sparse. Additionally, it covers operations for doubly and circular linked lists, and merging sorted linked lists.

Uploaded by

Sankit Ingale
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
27 views108 pages

Algorithm: Sum and Average of Array Elements

The document outlines various algorithms for operations on arrays, strings, and linked lists, including calculating sums and averages, inserting and deleting elements, and reversing linked lists. It also explains memory representation for 2D arrays and sparse matrices, along with algorithms for checking if a matrix is sparse. Additionally, it covers operations for doubly and circular linked lists, and merging sorted linked lists.

Uploaded by

Sankit Ingale
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 108

1.

algorithm to find and print the sum and average of elements in an array:

Algorithm: Sum and Average of Array Elements

Input: An array arr of size n.


Output: Sum and Average of the array elements.

1.
Start

2.
Initialize sum = 0.

3.
Read the size of the array, n.

4.
Repeat for each element in the array (from index i = 0 to n - 1):
a. Add the value of arr[i] to sum.

5.
Calculate the average: average = sum / n.

6.
Print sum and average.

7.
End

2. Write algorithms to perform following operations in an array

a) Insert element in an array.

b) Delete an element in an array.

c) Remove duplicate elements from an array


a) Insert an Element in an Array

Input: An array arr of size n, element x to insert, and position pos.


Output: Updated array after insertion.

1.
Start

2.
Read the size of the array n.

3.
Read the array elements.

4.
Read the element x and position pos.

5.
Shift all elements from position pos to the right by one position.
6.
Insert x at position pos.

7.
Increment the size of the array (n = n + 1).

8.
Print the updated array.

9.
End

b) Delete an Element from an Array

Input: An array arr of size n and position pos to delete.


Output: Updated array after deletion.

1.
Start

2.
Read the size of the array n.
3.
Read the array elements.

4.
Read the position pos to delete.

5.
Shift all elements from position pos + 1 to the left by one position.

6.
Decrease the size of the array (n = n - 1).

7.
Print the updated array.

8.
End

c) Remove Duplicate Elements from an Array

Input: An array arr of size n.


Output: Array with duplicates removed.

1.
Start

2.
Read the size of the array n.

3.
Read the array elements.

4.
Create an empty list unique.

5.
Repeat for each element in arr:
a. If the element is not in unique, add it to unique.

6.
Replace arr with unique.

7.
Print the updated array.

8.
End
3. Write an algorithm a) To find the smallest & largest elements in an array b) To merge the elements of two arrays in a third array in a sorted
manner

a) Find the Smallest and Largest Elements in an Array

Input: An array arr of size n.


Output: Smallest and largest elements in the array.

1.
Start

2.
Read the size of the array n.

3.
Read the elements of the array arr.

4.
Initialize smallest = arr[0] and largest = arr[0].

5.
Repeat for each element in arr (from index i = 1 to n - 1):
a. If arr[i] < smallest, update smallest = arr[i].
b. If arr[i] > largest, update largest = arr[i].

6.
Print smallest and largest.

7.
End

b) Merge Two Arrays in Sorted Order

Input: Two sorted arrays arr1 of size n1 and arr2 of size n2.
Output: A third array arr3 containing all elements in sorted order.
1.
Start

2.
Read the size of arrays n1 and n2.

3.
Read elements of arrays arr1 and arr2.

4.
Initialize pointers i = 0, j = 0, and k = 0 for arrays arr1, arr2, and arr3, respectively.

5.
Repeat until either i == n1 or j == n2:
a. If arr1[i] < arr2[j], assign arr3[k] = arr1[i] and increment i and k.
b. Else, assign arr3[k] = arr2[j] and increment j and k.

6.
Copy any remaining elements from arr1 to arr3.

7.
Copy any remaining elements from arr2 to arr3.

8.
Print arr3.

9.
End

4. Explain the memory representation of a 2D array & sparse matrix and write an algorithm to check if a matrix is sparse.

1. Memory Representation of a 2D Array

A 2D array is stored in contiguous memory locations in either row-major order or column-major order.

1.
Row-Major Order:

Elements are stored row by row.


Address(A[i][j]) = Base_Address + [ (i × Total_Columns) + j ] × Element_Size
2.Column-Major Order:

Elements are stored column by column.

Address(A[i][j]) = Base_Address + [ (j × Total_Rows) + i ] × Element_Size

Example

For a 2D array:

Copy code A = [ [10, 20, 30], [40, 50, 60]]

Row-Major Order Storage:


10, 20, 30, 40, 50, 60

Column-Major Order Storage:


10, 40, 20, 50, 30, 60

2. Memory Representation of a Sparse Matrix

A sparse matrix is a matrix in which most of the elements are zero. Instead of storing all elements, we only store non-zero elements using Triple
Representation:

Algorithm to Check if a Matrix is Sparse

Input: A matrix A of size m × n.


Output: Whether the matrix is sparse or not.

Algorithm

1.
Start

2.
Read the dimensions of the matrix m and n.

3.
Initialize a counter count = 0.

4.
Loop through each element of the matrix:
a. If the element is 0, increment count.

5.
Calculate total elements: total = m × n.
6.
If count > total / 2:
a. Print "Sparse Matrix".

7.
Else:
a. Print "Not Sparse".

8.
End

5. Write algorithms to perform following operations on a string. a) Reverse a string b) Check for a pattern in a string. c) Concatenate two strings

Algorithms for String Operations

a) Reverse a String

Input: A string S of length n.


Output: Reversed string.
Algorithm:

1.
Start

2.
Read the string S.

3.
Initialize an empty string Rev.

4.
Loop through the string from the last character to the first:
a. Append each character to Rev.

5.
Print Rev.

6.
End

b) Check for a Pattern in a String


Input: A string S and a pattern P.
Output: Position of the pattern if found, otherwise -1.

Algorithm:

1.
Start

2.
Read the string S and pattern P.

3.
Loop through S to find a match for P:
a. Compare substring of length len(P) with P.

4.
If a match is found, return the starting index.

5.
If no match is found, return -1.

6.
End
c) Concatenate Two Strings

Input: Two strings S1 and S2.


Output: Concatenated string S3.

Algorithm:

1.
Start

2.
Read strings S1 and S2.

3.
Concatenate S1 and S2 using the + operator.

4.
Print the result.

5.
End

6. Write an algorithms to insert and delete a node in a singly linked list at following positions. a) Beginning b) Middle c) End. d) Empty linked list
Algorithms for Insertion and Deletion in a Singly Linked List

A. Insertion in a Singly Linked List

a) Insert at the Beginning

Input: A linked list L and a node N with data.


Output: Updated linked list with N at the beginning.

Algorithm:

1.
Start

2.
Create a new node N.

3.
Set N.next = Head.
4.
Update Head = N.

5.
End

b) Insert in the Middle

Input: A linked list L, a position pos, and a node N with data.


Output: Updated linked list with N inserted at position pos.

Algorithm:

1.
Start

2.
Traverse the list to position pos - 1.

3.
Create a new node N.

4.
Set N.next = Current.next.

5.
Update Current.next = N.

6.
End

c) Insert at the End

Input: A linked list L and a node N with data.


Output: Updated linked list with N at the end.

Algorithm:

1.
Start

2.
Traverse the list until Current.next = NULL.
3.
Create a new node N.

4.
Set Current.next = N.

5.
Update N.next = NULL.

6.
End

d) Insert in an Empty Linked List

Input: An empty linked list L and a node N with data.


Output: Updated linked list with N as the first node.

Algorithm:

1.
Start

2.
Create a new node N.

3.
Set Head = N.

4.
Update N.next = NULL.

5.
End

B. Deletion in a Singly Linked List

a) Delete from the Beginning

Input: A linked list L.


Output: Updated linked list without the first node.

Algorithm:

1.
Start
2.
If the list is empty, print "Underflow" and exit.

3.
Set Head = Head.next.

4.
Delete the old first node. 5.End

b) Delete from the Middle

Input: A linked list L and a position pos.


Output: Updated linked list with the node at position pos deleted.

Algorithm:

1.
Start

2.
Traverse the list to position pos - 1.

3.
Set Current.next = Current.next.next.

4.
Delete the node at position pos.

5.
End

c) Delete from the End

Input: A linked list L.


Output: Updated linked list without the last node.

Algorithm:

1.
Start

2.
Traverse the list until Current.next.next = NULL.

3.
Set Current.next = NULL.
4.
Delete the last node.

5.
End

d) Delete from an Empty Linked List

Input: An empty linked list L.


Output: Print "Underflow".

Algorithm:

1.
Start

2.
If Head == NULL, print "Underflow" and exit.

3.
End
7. Write an algorithm to insert and delete a node on doubly and circular linked list at following positions. a) Beginning b) Middle c) End. d)
Empty linked list

A. Doubly Linked List (DLL)

1. Insertion in Doubly Linked List

a) Insert at the Beginning

Input: Doubly linked list L and a node N.


Output: Updated list with N at the beginning.

Algorithm:

1.
Start
2.
Create a new node N.

3.
Set N.next = Head.

4.
If Head ≠ NULL, set Head.prev = N.

5.
Update Head = N.

6.
Set N.prev = NULL.

7.
End

b) Insert in the Middle

Input: Doubly linked list L, position pos, and a node N.


Output: Updated list with N inserted at position pos.
Algorithm:

1.
Start

2.
Traverse to position pos - 1.

3.
Create a new node N.

4.
Set N.next = Current.next.

5.
Set N.prev = Current.

6.
If Current.next ≠ NULL, update Current.next.prev = N.

7.
Update Current.next = N.

8.
End
c) Insert at the End

Input: Doubly linked list L and a node N.


Output: Updated list with N at the end.

Algorithm:

1.
Start

2.
Traverse to the last node.

3.
Create a new node N.

4.
Set Last.next = N.

5.
Set N.prev = Last.

6.
Update N.next = NULL.

7.
End

d) Insert in an Empty List

Input: An empty DLL and a node N.


Output: List with N as the only node.

Algorithm:

1.
Start

2.
Create a new node N.

3.
Set Head = N.

4.
Update N.next = NULL and N.prev = NULL.
5.
End

2. Deletion in Doubly Linked List

a) Delete from the Beginning

Algorithm:

1.
Start

2.
If Head == NULL, print "Underflow" and exit.

3.
Update Head = Head.next.

4.
Set Head.prev = NULL.

5.
End

b) Delete from the Middle

Algorithm:

1.
Start

2.
Traverse to position pos.

3.
Set Current.prev.next = Current.next.

4.
If Current.next ≠ NULL, set Current.next.prev = Current.prev.

5.
Delete Current.

6.
End
c) Delete from the End

Algorithm:

1.
Start

2.
Traverse to the last node.

3.
Set Last.prev.next = NULL.

4.
Delete Last.

5.
End
d) Delete from an Empty List

Algorithm:

1.
Start

2.
If Head == NULL, print "Underflow" and exit.

3.
End

B. Circular Linked List (CLL)

1. Insertion in Circular Linked List


a) Insert at the Beginning

Algorithm:

1.
Start

2.
Create a new node N.

3.
If Head == NULL:
a. Set N.next = N.
b. Set Head = N.

4.
Else:
a. Traverse to the last node.
b. Set N.next = Head.
c. Set Last.next = N.
d. Update Head = N.

5.
End
b) Insert in the Middle

Algorithm:

1.
Start

2.
Traverse to position pos - 1.

3.
Create a new node N.

4.
Set N.next = Current.next.

5.
Update Current.next = N.

6.
End
c) Insert at the End

Algorithm:

1.
Start

2.
Create a new node N.

3.
Traverse to the last node.

4.
Set Last.next = N.

5.
Update N.next = Head.

6.
End
d) Insert in an Empty List

Algorithm:

1.
Start

2.
Create a new node N.

3.
Set N.next = N.

4.
Update Head = N.

5.
End

2. Deletion in Circular Linked List

a) Delete from the Beginning


Algorithm:

1.
Start

2.
If Head == NULL, print "Underflow" and exit.

3.
Traverse to the last node.

4.
Set Head = Head.next.

5.
Update Last.next = Head.

6.
End

b) Delete from the Middle

Algorithm:
1.
Start

2.
Traverse to position pos - 1.

3.
Set Current.next = Current.next.next.

4.
End

c) Delete from the End

Algorithm:

1.
Start

2.
Traverse to the second last node.

3.
Update Current.next = Head.

4.
End

d) Delete from an Empty List

Algorithm:

1.
Start

2.
If Head == NULL, print "Underflow" and exit.

3.
End

8. Write an algorithm for following operations a) To reverse a singly linked list. b) To merge two sorted linked lists into a third sorted list.
Algorithms for Linked List Operations

A) Reverse a Singly Linked List

Input: A singly linked list L with n nodes.


Output: Reversed linked list.

Algorithm:

1.
Start

2.
Initialize three pointers:

Prev = NULL

Current = Head
Next = NULL

4.
Repeat until Current != NULL:
a. Set Next = Current.next.
b. Update Current.next = Prev.
c. Move Prev = Current.
d. Move Current = Next.

5.
Update Head = Prev.

6.
End

B) Merge Two Sorted Linked Lists into a Third Sorted List

Input: Two sorted linked lists L1 and L2.


Output: A third sorted linked list L3.

Algorithm:

1.
Start
2.
Create a dummy node Dummy and set Tail = Dummy.

3.
Repeat until either L1 or L2 is NULL:
a. If L1.data ≤ L2.data:

Set Tail.next = L1.

Move L1 = L1.next.
b. Else:

Set Tail.next = L2.

Move L2 = L2.next.
c. Move Tail = Tail.next.

5.
Attach the remaining nodes of the non-empty list:
a. If L1 ≠ NULL, set Tail.next = L1.
b. If L2 ≠ NULL, set Tail.next = L2.
6.
Return Dummy.next as the head of the merged list.

7.
End

9. Let A and B be two sorted linked list. Write an algorithm to create a third linked list C, which will have the elements from both A and B but in a
sorted manner. If you run out of the elements of one list, then append the remaining elements of other list in C.

Algorithm
1.
Start

2.
Create a dummy node Dummy and initialize Tail = Dummy.

3.
While both A ≠ NULL and B ≠ NULL:
a. If A.data ≤ B.data:

Set Tail.next = A.
Move A = A.next.
b. Else:

Set Tail.next = B.

Move B = B.next.
c. Move Tail = Tail.next.

5.
Append remaining elements:
a. If A ≠ NULL:

Set Tail.next = A.
b. If B ≠ NULL:

Set Tail.next = B.

7.
Return Dummy.next as the head of the merged list C.
8.
End

10. Write an algorithms to perform stack operations (push, pop, peek, and traverse) using arrays and linked lists.

A. Stack Operations Using Arrays

A stack is a data structure that follows the Last In First Out (LIFO) principle. Using an array, the stack operations are performed as follows:

1. Push Operation (Insert element into stack)

Input: A stack S implemented using an array, an element x.


Output: Stack S with the element x added.

Algorithm:
1.
Start

2.
If the stack is full (i.e., index top == max_size - 1), print "Stack Overflow" and exit.

3.
Increment the top index by 1.

4.
Set S[top] = x.

5.
End

2. Pop Operation (Remove element from stack)

Input: A stack S implemented using an array.


Output: The element removed from the stack.

Algorithm:

1.
Start

2.
If the stack is empty (i.e., top == -1), print "Stack Underflow" and exit.

3.
Set element = S[top].

4.
Decrement the top index by 1.

5.
Return element.

6.
End

3. Peek Operation (View top element of stack)

Input: A stack S implemented using an array.


Output: The top element of the stack.

Algorithm:
1.
Start

2.
If the stack is empty (i.e., top == -1), print "Stack is empty" and exit.

3.
Return S[top].

4.
End

4. Traverse Operation (View all elements in the stack)

Input: A stack S implemented using an array.


Output: All elements in the stack.

Algorithm:

1.
Start

2.
If the stack is empty (i.e., top == -1), print "Stack is empty" and exit.

3.
For i = top to 0 (from top to bottom):

Print S[i].

5.
End

B. Stack Operations Using Linked Lists

In a linked list-based stack, each node holds an element and a reference to the next node in the stack.

1. Push Operation (Insert element into stack)

Input: A stack S implemented using a linked list, an element x.


Output: Stack S with the element x added.
Algorithm:

1.
Start

2.
Create a new node new_node with data x.

3.
Set new_node.next = Head (link it to the current top).

4.
Set Head = new_node.

5.
End

2. Pop Operation (Remove element from stack)

Input: A stack S implemented using a linked list.


Output: The element removed from the stack.

Algorithm:
1.
Start

2.
If the stack is empty (i.e., Head == NULL), print "Stack Underflow" and exit.

3.
Set element = Head.data.

4.
Set Head = Head.next (move the top to the next node).

5.
Return element.

6.
End

3. Peek Operation (View top element of stack)

Input: A stack S implemented using a linked list.


Output: The top element of the stack.
Algorithm:

1.
Start

2.
If the stack is empty (i.e., Head == NULL), print "Stack is empty" and exit.

3.
Return Head.data.

4.
End

4. Traverse Operation (View all elements in the stack)

Input: A stack S implemented using a linked list.


Output: All elements in the stack.

Algorithm:

1.
Start
2.
If the stack is empty (i.e., Head == NULL), print "Stack is empty" and exit.

3.
Set Current = Head.

4.
While Current != NULL:

Print Current.data.

Set Current = Current.next.

6.
End

11. Write an algorithms to perform all operations on queue and linked queue.
A. Queue Operations Using Array

For an array-based queue, we'll maintain an array Q and two pointers: front (points to the first element) and rear (points to the last element).

1. Enqueue Operation (Insert element into queue)

Input: A queue Q implemented using an array, an element x.


Output: Queue Q with the element x added at the rear.

Algorithm:

1.
Start

2.
If the queue is full (i.e., rear == max_size - 1), print "Queue Overflow" and exit.

3.
Increment rear by 1.

4.
Set Q[rear] = x.
5.
If the queue was empty (i.e., front == -1), set front = 0.

6.
End

2. Dequeue Operation (Remove element from queue)

Input: A queue Q implemented using an array.


Output: The element removed from the front of the queue.

Algorithm:

1.
Start

2.
If the queue is empty (i.e., front == -1), print "Queue Underflow" and exit.

3.
Set element = Q[front].

4.
If front == rear, set front = rear = -1 (queue is empty).

5.
Else, increment front by 1.

6.
Return element.

7.
End

3. Peek Operation (View front element of queue)

Input: A queue Q implemented using an array.


Output: The front element of the queue.

Algorithm:

1.
Start

2.
If the queue is empty (i.e., front == -1), print "Queue is empty" and exit.
3.
Return Q[front].

4.
End

4. Traverse Operation (View all elements in the queue)

Input: A queue Q implemented using an array.


Output: All elements in the queue from front to rear.

Algorithm:

1.
Start

2.
If the queue is empty (i.e., front == -1), print "Queue is empty" and exit.

3.
For i = front to rear:
Print Q[i].

5.
End

B. Queue Operations Using Linked List

For a linked list-based queue, we use a singly linked list where each node contains an element and a reference to the next node. We'll maintain
two pointers: front (points to the first node) and rear (points to the last node).

1. Enqueue Operation (Insert element into queue)

Input: A queue Q implemented using a linked list, an element x.


Output: Queue Q with the element x added at the rear.

Algorithm:

1.
Start

2.
Create a new node new_node with data x and new_node.next = NULL.

3.
If the queue is empty (i.e., front == NULL):

Set front = rear = new_node.

5.
Else:

Set rear.next = new_node.

Update rear = new_node.

7.
End

2. Dequeue Operation (Remove element from queue)

Input: A queue Q implemented using a linked list.


Output: The element removed from the front of the queue.

Algorithm:

1.
Start

2.
If the queue is empty (i.e., front == NULL), print "Queue Underflow" and exit.

3.
Set element = front.data.

4.
Update front = front.next.

5.
If front == NULL, set rear = NULL (queue is now empty).

6.
Return element.

7.
End
3. Peek Operation (View front element of queue)

Input: A queue Q implemented using a linked list.


Output: The front element of the queue.

Algorithm:

1.
Start

2.
If the queue is empty (i.e., front == NULL), print "Queue is empty" and exit.

3.
Return front.data.

4.
End

4. Traverse Operation (View all elements in the queue)

Input: A queue Q implemented using a linked list.


Output: All elements in the queue from front to rear.

Algorithm:

1.
Start

2.
If the queue is empty (i.e., front == NULL), print "Queue is empty" and exit.

3.
Set current = front.

4.
While current != NULL:

Print current.data.

Set current = current.next.

6.
End
12. Write the array representation of a tree in memory with proper example

Array Representation of a Tree in Memory

In an array-based representation of a binary tree, the tree is stored in an array where each element corresponds to a node in the tree. The
position of each node in the array is determined by the following rules:

Root is at index 0.

For any node at index i:

The left child is at index 2*i + 1.


The right child is at index 2*i + 2.

The parent is at index (i - 1) / 2 (integer division).

This method works well for complete binary trees or binary trees that are mostly balanced, as there are no gaps in the array representation.

Example

Consider the following binary tree:

markdown

/ \

2 3
/\ /\

4 56 7

Step-by-Step Array Representation


1.
Node 1 (Root): The root node 1 is at index 0.

2.
Node 2 (Left Child of 1): The left child of 1 is 2, which is at index 2*0 + 1 = 1.

3.
Node 3 (Right Child of 1): The right child of 1 is 3, which is at index 2*0 + 2 = 2.

4.
Node 4 (Left Child of 2): The left child of 2 is 4, which is at index 2*1 + 1 = 3.

5.
Node 5 (Right Child of 2): The right child of 2 is 5, which is at index 2*1 + 2 = 4.
6.
Node 6 (Left Child of 3): The left child of 3 is 6, which is at index 2*2 + 1 = 5.

7.
Node 7 (Right Child of 3): The right child of 3 is 7, which is at index 2*2 + 2 = 6.

Array Representation

Thus, the tree will be represented as:

csharp

Copy code

[1, 2, 3, 4, 5, 6, 7]

14. Create a binary search tree for given values and write recursive algorithms for insertion and searching. Print in-order , pre-order, post-order
traversals.
2. Recursive Algorithms for Insertion and Searching

a) Recursive Insertion in a BST

Algorithm:

1.
If the tree is empty, create a new node with the given value.

2.
If the value to insert is smaller than the current node, recursively insert into the left subtree.

3.
If the value to insert is greater than the current node, recursively insert into the right subtree.

Algorithm (Pseudocode):

plaintext

Copy code

Function Insert(root, value):


If root is NULL:

Return new Node(value)

If value < root.data:

root.left = Insert(root.left, value)

Else:

root.right = Insert(root.right, value)

Return root

b) Recursive Search in a BST

Algorithm:

1.
If the tree is empty, return NULL (value not found).

2.
If the value matches the current node, return the node.

3.
If the value is smaller, recursively search the left subtree.

4.
If the value is greater, recursively search the right subtree.

Algorithm (Pseudocode):

plaintext

Copy code

Function Search(root, value):

If root is NULL:

Return NULL
If root.data == value:

Return root

If value < root.data:

Return Search(root.left, value)

Else:

Return Search(root.right, value)

3. Tree Traversals

a) In-order Traversal (Left, Root, Right)

In this traversal, we visit the left subtree, the root node, and then the right subtree.

Algorithm:

plaintext
Copy code

Function InOrder(root):

If root is NULL:

Return

InOrder(root.left)

Print root.data

InOrder(root.right)

In-order Traversal of the Tree:


20, 30, 40, 50, 60, 70, 80

b) Pre-order Traversal (Root, Left, Right)


In this traversal, we visit the root node first, then the left subtree, and finally the right subtree.

Algorithm:

plaintext

Copy code

Function PreOrder(root):

If root is NULL:

Return

Print root.data

PreOrder(root.left)

PreOrder(root.right)
Pre-order Traversal of the Tree:
50, 30, 20, 40, 70, 60, 80

c) Post-order Traversal (Left, Right, Root)

In this traversal, we visit the left subtree, then the right subtree, and finally the root node.

Algorithm:

plaintext

Copy code

Function PostOrder(root):

If root is NULL:

Return

PostOrder(root.left)

PostOrder(root.right)
Print root.data

Post-order Traversal of the Tree:


20, 40, 30, 60, 80, 70, 50

15. Create a binary search tree for given values and write recursive algorithms for deletion and balancing process.

Binary Search Tree (BST) Operations: Deletion and Balancing

1. Create a Binary Search Tree for Given Values

Let's use the same set of values: [50, 30, 20, 40, 70, 60, 80]

BST Structure:

markdown
Copy code

50

/ \

30 70

/ \ / \

20 40 60 80

2. Recursive Deletion in a BST

Deletion Cases:
1.
Node to delete has no children (leaf node): Simply remove the node.

2.
Node to delete has one child: Replace the node with its child.

3.
Node to delete has two children: Find the in-order successor (smallest node in the right subtree) or in-order predecessor (largest node in the
left subtree), replace the node with the successor/predecessor, and delete the successor/predecessor recursively.

Algorithm (Pseudocode):

plaintext

Copy code

Function Delete(root, value):

If root is NULL:

Return NULL

If value < root.data:

root.left = Delete(root.left, value)

ElseIf value > root.data:

root.right = Delete(root.right, value)


Else:

If root.left is NULL:

Return root.right

ElseIf root.right is NULL:

Return root.left

Else:

successor = FindMin(root.right)

root.data = successor.data

root.right = Delete(root.right, successor.data)

Return root

3. Balancing a BST (AVL Tree Approach)


Balancing Factor:

The balance factor of a node is the height difference between the left and right subtrees.

If the balance factor is > 1, the tree is left-heavy (requires right rotation).

If the balance factor is < -1, the tree is right-heavy (requires left rotation).

Algorithm (Pseudocode):

plaintext

Copy code

Function Balance(root):

If root is NULL:

Return NULL
root.left = Balance(root.left)

root.right = Balance(root.right)

balance_factor = Height(root.left) - Height(root.right)

If balance_factor > 1:

If Height(root.left.left) > Height(root.left.right):

root = RightRotate(root)

Else:

root.left = LeftRotate(root.left)

root = RightRotate(root)
If balance_factor < -1:

If Height(root.right.right) > Height(root.right.left):

root = LeftRotate(root)

Else:

root.right = RightRotate(root.right)

root = LeftRotate(root)

Return root

16. For the given BST, Write a recursive algorithm to a) Count the total number of nodes in a BST. b) Find smallest node of a BST c) Find largest
node of a BST
Recursive Algorithms for Binary Search Tree (BST)

a) Count the Total Number of Nodes in a BST

Algorithm:

1.
If the root is NULL, return 0.

2.
Recursively count the nodes in the left subtree.

3.
Recursively count the nodes in the right subtree.

4.
Total nodes = 1 (current node) + left subtree count + right subtree count.

plaintext
Copy code

Function CountNodes(root):

If root is NULL:

Return 0

Return 1 + CountNodes(root.left) + CountNodes(root.right)

b) Find the Smallest Node in a BST

Algorithm:

1.
Start from the root.

2.
Keep traversing the left child until you reach a NULL left child.

3.
The node at the end is the smallest.
plaintext

Copy code

Function FindMin(root):

If root is NULL:

Return NULL

If root.left is NULL:

Return root

Return FindMin(root.left

c) Find the Largest Node in a BST

Algorithm:

1.
Start from the root.

2.
Keep traversing the right child until you reach a NULL right child.

3.
The node at the end is the largest.

plaintext

Copy code

Function FindMax(root):

If root is NULL:

Return NULL

If root.right is NULL:

Return root
Return FindMax(root.right)

17. Explain the representation of a graph in a memory with a proper example

Graph Representation in Memory Graphs can be represented in memory using two common methods: Adjacency Matrix and Adjacency List.

1. Adjacency Matrix:

A 2D matrix where rows and columns represent the vertices of the graph.

If there is an edge between vertex i and vertex j, the element at matrix position [i][j] is marked (usually with a 1 or the edge weight). If no
edge exists, it's marked as 0 or infinity (for weighted graphs).

Works well for dense graphs.


Example: Consider the following graph:

markdown

Copy code

/ \

0 2

\ /

Adjacency Matrix:

Css
0 1 2 3

0 [0, 1, 0, 1]

1 [1, 0, 1, 0]

2 [0, 1, 0, 1]

3 [1, 0, 1, 0]

2. Adjacency List:

An array of lists (or a hash map), where each list stores the neighbors of a vertex.

Each vertex has a list containing all its adjacent vertices.

Works well for sparse graphs.

Example (using the same graph as above):


markdown

Copy code

/ \

0 2

\ /

Adjacency List:

makefile

0: [1, 3]

1: [0, 2]
2: [1, 3]

3: [0, 2]

18. Write recursive algorithms for in-order, pre-order, and post-order traversals of a binary search tree.

Recursive Algorithms for Binary Search Tree (BST) Traversals

Given a Binary Search Tree (BST), here are the recursive algorithms for in-order, pre-order, and post-order traversals:

1. In-order Traversal (Left, Root, Right)

Algorithm:

1.
Traverse the left subtree.

2.
Visit the root node.

3.
Traverse the right subtree.

Recursive Algorithm:

plaintext

Copy code

Function InOrder(root):

If root is NULL:

Return

InOrder(root.left) // Traverse left subtree

Print root.data // Visit root node

InOrder(root.right) // Traverse right subtree


2. Pre-order Traversal (Root, Left, Right)

Algorithm:

1.
Visit the root node.

2.
Traverse the left subtree.

3.
Traverse the right subtree.

Recursive Algorithm:

plaintext

Copy code

Function PreOrder(root):
If root is NULL:

Return

Print root.data // Visit root node

PreOrder(root.left) // Traverse left subtree

PreOrder(root.right) // Traverse right subtree

3. Post-order Traversal (Left, Right, Root)

Algorithm:

1.
Traverse the left subtree.

2.
Traverse the right subtree.

3.
Visit the root node.
Recursive Algorithm:

plaintext

Copy code

Function PostOrder(root):

If root is NULL:

Return

PostOrder(root.left) // Traverse left subtree

PostOrder(root.right) // Traverse right subtree

Print root.data // Visit root node


19. Write an algorithm to perform breadth-first search (BFS) and depth-first search (DFS) on a given graph.

Breadth-First Search (BFS) and Depth-First Search (DFS) Algorithms

Given a graph with vertices and edges, here are the algorithms to perform Breadth-First Search (BFS) and Depth-First Search (DFS).

1. Breadth-First Search (BFS) BFS explores all neighbors of a node before moving to the next level of nodes. It uses a queue for traversal.

Algorithm:

1.
Start with the source node, mark it as visited, and enqueue it.

2.
While the queue is not empty:

Dequeue a node and print it.


For each unvisited neighbor of the node, mark it as visited and enqueue it.

Pseudocode

Function BFS(graph, start):

Create a queue Q

Create a set visited to keep track of visited nodes

Enqueue start node into Q

Mark start node as visited

While Q is not empty:

current = Dequeue from Q


Print current (or process current node)

For each neighbor of current in graph:

If neighbor is not visited:

Enqueue neighbor into Q

Mark neighbor as visited

mathematica

Copy code

A -- B -- D
| |

C -- E

BFS Traversal from A:


A B C D E

2. Depth-First Search (DFS)

DFS explores as far as possible along a branch before backtracking. It can be implemented using recursion or a stack.

DFS (Recursive)

Algorithm:

1.
Start with the source node, mark it as visited.

2.
Recursively visit all unvisited neighbors of the current node.

Function DFS(graph, node, visited):


Mark node as visited

Print node (or process the node)

For each neighbor of node in graph:

If neighbor is not visited:

DFS(graph, neighbor, visited)

DFS (Using Stack)

Algorithm:
1.
Start with the source node, mark it as visited, and push it onto the stack.

2.
While the stack is not empty:

Pop a node from the stack and print it.


For each unvisited neighbor of the node, mark it as visited and push it onto the stack.

Function DFS(graph, start):

Create a stack S

Create a set visited to keep track of visited nodes

Push start node onto S

Mark start node as visited

While S is not empty:

current = Pop from S


Print current (or process current node)

For each neighbor of current in graph:

If neighbor is not visited:

Push neighbor onto S

Mark neighbor as visited

20. Explain the memory representation of a graph with examples

Memory Representation of a Graph

Graphs can be represented in memory using two common methods: Adjacency Matrix and Adjacency List.
1. Adjacency Matrix:

A 2D array (matrix) where each row and column represent a vertex.

If there is an edge between vertex i and vertex j, matrix[i][j] is marked (1 for unweighted, or the edge weight for weighted graphs).

Suitable for dense graphs.

Example:Graph:

A -- B -- D

| |

C -- E
Adjacency Matrix:

ABCDE

A[01100]

B[10011]

C[10001]

D[01000]

E[01100]

2. Adjacency List:

An array (or linked list) of lists, where each list stores the neighbors of a vertex.

Suitable for sparse graphs.


Example:

mathematica

Copy code

Graph:

A -- B -- D

| |

C -- E

Adjacency List:

A: [B, C]

B: [A, D, E]
C: [A, E]

D: [B]

E: [B, C]

a) Write an algorithm to calculate sum of data of alternate nodes of doubly linked list. Algorithm:

SumOfAlternateNodes

Input: Head node of a doubly linked list

1. Initialize a variable sum to 0.

2. Set a flag variable isAlternate to true.


3. Traverse the doubly linked list:

a. If isAlternate is true, add the data of the current node to the sum.

b. Toggle the value of isAlternate.

c. Move to the next node.

4. The sum now contains the sum of data of alternate nodes in the doubly linked list.

Pseudocode:

Algorithm SumOfAlternateNodes(head): // Step 1 sum = 0 // Step 2 isAlternate = true //

Step 3 current = head while current is not null: //

Step 3 a if isAlternate: sum += current.data //

Step 3b isAlternate = not isAlternate //

Step 3c current = current.next // Step 4 return sum

You might also like