DS-3
DS-3
Data Structures
|
------------------------------------------------
| |
Linear Data Structures Non-Linear Data Structures
| |
--------------- -----------------------
| | | |
Arrays Linked Lists Trees Graphs
|
Stacks
|
Queues
### Explanation:
1. *Linear Data Structures*: Elements are arranged in a sequential manner.
- *Arrays*: Fixed-size, contiguous memory allocation.
- *Linked Lists*: Elements are stored as nodes, with each node pointing to the next.
- *Stacks*: LIFO (Last In, First Out) structure.
- *Queues*: FIFO (First In, First Out) structure.
1b) Apply the binary search algoritin on the following sorted wray to fiad the targe
SMI element?
12 23 34 45 56 67 78 89 98 123
A) To apply the binary search algorithm on the given sorted array and find the target element (89) in
C, here’s the approach:
Sorted Array:
12,23,34,45,56,67,78,89,98,12312, 23, 34, 45, 56, 67, 78, 89, 98, 123
Target Element:
89
1. Initialize:
2. Iterate:
If the element at mid is less than the target, update left to mid + 1 to search
the right half.
If the element at mid is greater than the target, update right to mid - 1 to
search the left half.
C Code:
#include <stdio.h>
if (arr[mid] == target) {
return mid;
left = mid + 1;
else {
right = mid - 1;
return -1;
int main() {
int arr[] = {12, 23, 34, 45, 56, 67, 78, 89, 98, 123};
if (result != -1) {
} else {
return 0;
Output:
A) To solve the problem of finding the frequently occurring elements in an array and displaying their
positions in C, we need to perform the following tasks:
Tasks:
Given Array:
2,1,5,2,3,6,9,1,22, 1, 5, 2, 3, 6, 9, 1, 2
Steps:
Find the maximum frequency and display the elements with that frequency along with their
positions.
C Code Implementation:
#include <stdio.h>
#include <stdlib.h>
int *positions[n];
freq[arr[i]]++;
positions[arr[i]][freq[arr[i]] - 1] = i;
int maxFreq = 0;
maxFreq = freq[arr[i]];
if (freq[arr[i]] == maxFreq) {
printf("\n");
free(positions[i]);
free(freq);
int main() {
findFrequentElements(arr, n);
return 0;
Output:-
Insertion sort is a simple sorting algorithm that builds the sorted array one element at a time. It
works similarly to how you might sort playing cards in your hands. You take one card at a time and
insert it into its correct position among the cards you’ve already sorted.
1. Start from the second element (since a single element is trivially sorted).
3. If the current element is smaller, shift the larger elements one position to the right.
Example:
Step-by-step Process:
Start with the second element (2), compare it with 5, and place 2 before 5.
C Code Implementation:
#include <stdio.h>
int i, key, j;
key = arr[i];
j = i - 1;
arr[j + 1] = arr[j
j = j - 1;
arr[j + 1] = key;
}
}
printf("\n");
int main() {
printArray(arr, n);
insertionSort(arr, n);
printArray(arr, n);
return 0;
Output:
Original array: 5 2 9 1 5 6
Sorted array: 1 2 5 5 6 9
A) Linked List: A Linked List is a linear data structure in which elements, called nodes, are stored in
memory in a non-contiguous manner. Each node contains two parts:
2. Pointer (or Link): A reference (or address) to the next node in the sequence. In the last
node, this pointer is typically NULL, indicating the end of the list.
Unlike arrays, linked lists do not require elements to be stored in contiguous memory locations.
Instead, each node points to the next one, allowing for dynamic memory allocation.
1. Singly Linked List: Each node contains a data part and a pointer to the next node.
2. Doubly Linked List: Each node has two pointers: one pointing to the next node and one
pointing to the previous node.
3. Circular Linked List: The last node points back to the first node instead of having a NULL
pointer.
struct Node {
int data;
};
1. Dynamic Size:
o The size of a linked list can grow or shrink dynamically at runtime. This is a key
advantage over arrays, where the size is fixed at the time of creation.
o Linked lists don’t need to declare a fixed size at the time of allocation.
2. Efficient Insertion/Deletion:
o Inserting or deleting nodes in a linked list can be done efficiently, especially at the
beginning or in the middle of the list. No shifting of elements is required, unlike in
arrays.
3. No Memory Waste:
o Linked lists use memory as needed (i.e., nodes are allocated dynamically). This
means there is no wasted space due to preallocated memory, which might happen
with arrays when you don’t know the exact size in advance.
o Since linked lists allocate memory only when needed, they avoid the potential
problem of wasted space when the size of an array is larger than needed.
o Linked lists do not support random access. To access an element, you must traverse
the list from the beginning, making it slower than arrays for access by index.
o Each node in a linked list requires extra memory for the pointer(s) that store the
address of the next node. This makes linked lists less memory efficient than arrays.
3. Complexity in Implementation:
o Linked lists are more complex to implement and manage compared to arrays.
Operations like insertion, deletion, and traversal require pointer manipulation,
which is prone to errors if not handled properly.
4. Sequential Access:
o To find an element, you have to traverse the list node by node. This makes
searching for elements slower than arrays where elements can be accessed by
index.
o In addition to the data, each node has to store a pointer (or two in the case of a
doubly linked list), which introduces an overhead compared to simple data
structures like arrays.
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
};
newNode->data = value;
newNode->next = NULL;
return newNode;
current = current->next;
printf("NULL\n");
int main() {
struct Node* head = createNode(10);
head->next = createNode(20);
head->next->next = createNode(30);
printList(head);
return 0;
Output:
3b) Build the logic for single linked list insertion operation with an example?
A) Sure! Let's break down the process of inserting a node in a singly linked list and implement it
step-by-step with a complete example in C.
A singly linked list is a data structure where each element (node) contains:
Insertion Operations
We can perform the following types of insertion operations in a singly linked list:
o Point the new node's next to the current head of the list.
o Otherwise, traverse the list to the last node and set its next to point to the new
node.
o Traverse the list until you reach the node just before the desired position.
o Update the next pointer of the previous node to point to the new node, and the next
pointer of the new node to point to the next node.
C Code Implementation
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
};
newNode->data = data;
newNode->next = NULL;
return newNode;
newNode->next = *head;
*head = newNode;
if (*head == NULL) {
*head = newNode;
return;
}
temp = temp->next;
temp->next = newNode;
if (position < 0) {
printf("Invalid position!\n");
return;
if (position == 0) {
insertAtBeginning(head, data);
return;
temp = temp->next;
if (temp == NULL) {
return;
newNode->next = temp->next;
temp->next = newNode;
temp = temp->next;
printf("NULL\n");
int main() {
insertAtBeginning(&head, 10);
insertAtBeginning(&head, 20);
insertAtEnd(&head, 30);
printList(head);
return 0;
Output:
4a) Construct an algorithm to Implement a Singly Linked List delction and traversing operations.
In a singly linked list, deletion and traversal operations are essential for managing data. Here's an
algorithm to implement these operations in C.
Operations:
1. Traversal:
o Traverse the list from the head to the last node and print each node's data.
2. Deletion:
Algorithm Explanation
1. Traversal:
o Traverse the list by following the next pointers until you reach NULL (the end of the
list).
o If not, point the head to the next node of the current head and free the memory of
the current head.
o Traverse the list until the second-to-last node (where next is NULL).
o Set the second-to-last node's next pointer to NULL and free the last node.
o Traverse the list until the node just before the specified position.
o Adjust the next pointers to remove the node at that position and free its memory.
C Code Implementation
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
};
newNode->next = NULL;
return newNode;
if (temp == NULL) {
temp = temp->next;
printf("NULL\n");
if (*head == NULL) {
return;
*head = temp->next
free(temp);
if (*head == NULL) {
return;
if (temp->next == NULL) {
*head = NULL;
free(temp);
Example Output:
4b) Discuss all possible cases for Double Linked List delction operation.
A)
o If the node to be deleted is the first node (head), we need to update the head
pointer and ensure the next node’s previous pointer is NULL.
o If the node to be deleted is the last node (tail), we need to update the tail pointer
and ensure the previous node’s next pointer is NULL.
o If the node to be deleted is neither the head nor the tail, we need to adjust the next
pointer of the previous node and the previous pointer of the next node to bypass the
node being deleted.
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
};
newNode->data = data;
newNode->next = NULL;
newNode->prev = NULL;
return newNode;
if (temp == NULL) {
return;
temp = temp->next;
printf("NULL\n");
}
void deleteAtBeginning(struct Node** head) {
if (*head == NULL) {
return;
*head = (*head)->next;
if (*head != NULL) {
(*head)->prev = NULL;
free(temp);
if (*head == NULL) {
return;
if (temp->next == NULL) {
*head = NULL;
free(temp);
return;
temp = temp->next;
temp->prev->next = NULL;
free(temp);
printf("Node deleted from the end.\n");
if (*head == NULL) {
return;
if (position == 0) {
deleteAtBeginning(head);
return;
temp = temp->next;
if (temp == NULL) {
return;
if (temp->next != NULL) {
temp->next->prev = temp->prev;
if (temp->prev != NULL) {
temp->prev->next = temp->next;
free(temp);
if (*head == NULL) {
deleteAtBeginning(head);
return;
temp = temp->next;
if (temp == NULL) {
return;
if (temp->next != NULL) {
temp->next->prev = temp->prev;
if (temp->prev != NULL) {
temp->prev->next = temp->next;
free(temp);
int main() {
head = createNode(10);
head->next = createNode(20);
head->next->prev = head;
head->next->next = createNode(30);
head->next->next->prev = head->next;
traverseList(head);
deleteAtBeginning(&head);
traverseList(head);
deleteAtEnd(&head);
traverseList(head);
deleteAtPosition(&head, 0);
traverseList(head);
deleteByValue(&head, 20);
traverseList(head);
return 0;
Example Output:
A) In C, both Linked Lists and Arrays are used to store collections of data, but they are fundamentally
different in terms of structure, memory allocation, and performance. Below is a detailed comparison
and contrast of Linked Lists and Arrays based on various factors:
Comparison Summary
Cache
Good (Contiguous Memory) Poor (Non-contiguous Memory)
Performance
5b) What is selection sort? Write an algorithm to implement Selection Sort with suitable example.
A) Selection Sort
Selection Sort is a simple sorting algorithm that works by repeatedly finding the minimum element
(or maximum, depending on the sorting order) from the unsorted part of the list and swapping it
with the first unsorted element. It is called "selection sort" because it repeatedly selects the smallest
(or largest) element and moves it to its correct position.
1. Start with the first element of the array and assume it is the minimum.
2. Compare it with the rest of the elements in the array to find the smallest element.
4. Move the boundary between the sorted and unsorted parts of the array to the right (i.e.,
consider the next element).
#include <stdio.h>
minIndex = i;
minIndex = j;
if (minIndex != i) {
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
printf("\n");
}
int main() {
printArray(arr, n);
selectionSort(arr, n);
printArray(arr, n);
return 0;
6a) Mention the drawback of Single Linked List and explain how to overcome them.
A Singly Linked List (SLL) is a linear data structure where each node contains a data element and a
pointer to the next node. While it has many advantages, it also comes with certain drawbacks. Here
are the key drawbacks and how to overcome them:
Can only traverse in one direction Use a doubly linked list or reverse
Reverse Traversal
(head to tail). the list iteratively.
Both Singly Linked List (SLL) and Doubly Linked List (DLL) are types of linked lists used to store
collections of data, but they differ significantly in their structure and behavior. Here’s a detailed
comparison between the two:
Summary of Differences
Node Structure Data + Next Pointer Data + Next Pointer + Prev Pointer
One-direction (Head to
Traversal Two-direction (Head to Tail, Tail to Head)
Tail)
Insertion/Deletion at
O(1) O(1)
Head
Property Singly Linked List Doubly Linked List
Insertion/Deletion at
O(n) O(1)
Tail
Insertion/Deletion in
O(n) O(1)
Middle
Difficult (requires
Reversing Easy (swap next/prev pointers)
traversal)