Linked List Data Structure Programms (1)
Linked List Data Structure Programms (1)
int main() {
struct Node* head = NULL; // Initialize the head to NULL
insertAtBeginning(&head, 10); // Insert 10 at the beginning
insertAtBeginning(&head, 20); // Insert 20 at the beginning
insertAtBeginning(&head, 30); // Insert 30 at the beginning
display(head); // Display the list
return 0;
}
/* Explanation:
1. The program defines a `Node` structure to represent a node in the list.
2. The `insertAtBeginning` function inserts a new node at the start of the
list.
3. A new node is created using `malloc`, its data is set, and it is linked to
the current head.
4. The head is updated to point to the newly inserted node.
5. The `display` function traverses the list from the head, printing each
node's data.
6. In `main`, we initialize the list and perform three insertions.
7. After inserting, we call `display` to print the entire list.
8. The nodes are inserted in reverse order since each new node becomes the
head.
9. The list is displayed as "30 -> 20 -> 10 -> NULL".
10. This demonstrates a basic insertion operation in a singly linked list.
*/
if (*head == NULL) {
*head = newNode; // If the list is empty, make the new node the head
return;
}
while (temp->next != NULL) {
temp = temp->next; // Traverse to the end of the list
}
temp->next = newNode; // Link the last node to the new node
}
int main() {
struct Node* head = NULL; // Initialize the head to NULL
insertAtEnd(&head, 10); // Insert 10 at the end
insertAtEnd(&head, 20); // Insert 20 at the end
insertAtEnd(&head, 30); // Insert 30 at the end
display(head); // Display the list
return 0;
}
/* Explanation:
1. The `insertAtEnd` function adds a new node at the end of the list.
2. A new node is created with `malloc`, and its `data` is set.
3. If the list is empty, the new node becomes the head.
4. Otherwise, the program traverses the list to reach the last node.
5. The `next` pointer of the last node is updated to point to the new node.
6. The `display` function prints the entire list from the head to the end.
7. In `main`, three nodes are inserted into the list.
8. The list is displayed as "10 -> 20 -> 30 -> NULL".
9. This operation ensures that nodes are appended at the end, regardless of
the list's size.
10. It provides an easy way to grow a linked list dynamically.
*/
int main() {
struct Node* head = NULL; // Initialize the head to NULL
head = (struct Node*)malloc(sizeof(struct Node)); // Create a new node
head->data = 10;
head->next = NULL;
/* Explanation:
1. The `deleteAtBeginning` function removes the first node of the list.
2. If the list is empty, a message is printed and the function returns.
3. The current head is stored in `temp`, and the head is updated to the next
node.
4. The old head node is freed from memory.
5. The `display` function traverses the list and prints each node's data.
6. In `main`, a node with data 10 is created and then deleted.
7. After deletion, the list becomes empty, so "NULL" is displayed.
8. This operation reduces the size of the list by one node from the front.
9. It's useful when removing elements from the start is needed.
10. It demonstrates the simplicity of deleting nodes from a singly linked
list.
*/
int main() {
struct Node* head = NULL;
head = (struct Node*)malloc(sizeof(struct Node)); // Create the head node
head->data = 10;
head->next = NULL;
insertAtEnd(&head, 20); // Insert 20 at the end
deleteAtEnd(&head); // Delete the last node
display(head); // Display the list
return 0;
}
/* Explanation:
1. The `deleteAtEnd` function removes the last node in the list.
2. If the list is empty, a message is printed, and the function returns.
3. If there’s only one node, it’s freed and the head is set to NULL.
4. Otherwise, the program traverses the list to find the second-last node.
5. The last node is freed and the second-last node's `next` pointer is set to
NULL.
6. The `display` function prints the list from the head node to the last
node.
7. In `main`, the list starts with one node and another is appended.
8. After deleting the last node, the list is displayed as "10 -> NULL".
9. This operation reduces the list size by removing the last node.
10. It's an efficient way to remove elements from the end of a singly linked
list.
*/
int main() {
struct Node* head = NULL;
head = (struct Node*)malloc(sizeof(struct Node)); // Create the head node
head->data = 10;
head->next = NULL;
if (search(head, 10)) {
printf("Element found.\n");
} else {
printf("Element not found.\n");
}
return 0;
}
/* Explanation:
1. The `search` function looks for a specific element in the list.
2. It iterates over each node in the list.
3. If the node's `data` matches the `key`, the function returns 1.
4. If the list is traversed completely without finding the key, it returns 0.
5. In `main`, the list is initialized with a single node containing data 10.
6. The `search` function is called to check if
the value 10 exists in the list.
7. The result is printed based on whether the element is found or not.
8. In this case, the element is found and "Element found." is printed.
9. This demonstrates how to search for an element in a singly linked list.
10. Searching can be used in applications that need to find specific data in
a list. */
int main() {
struct Node* head = NULL;
head = (struct Node*)malloc(sizeof(struct Node)); // Create the head node
head->data = 10;
head->next = NULL;
/* Explanation:
1. The `reverse` function reverses the entire linked list.
2. We use three pointers: `prev`, `current`, and `next`.
3. Traverse the list, updating each node's `next` pointer to point to the
previous node.
4. At the end of the loop, `prev` points to the new head of the list.
5. The `display` function prints the list from head to tail.
6. In `main`, three nodes are inserted into the list, and the list is
reversed.
7. After reversal, the list is displayed in reverse order as "30 -> 20 -> 10
-> NULL".
8. This operation changes the list from the original order to the opposite.
9. Reversing the list can be helpful in various scenarios like undo
operations.
10. The logic demonstrates the fundamental algorithm of reversing a singly
linked list.
*/
int main() {
struct Node* head = NULL;
head = (struct Node*)malloc(sizeof(struct Node)); // Create the head node
head->data = 10;
head->next = NULL;
/* Explanation:
1. The `length` function calculates the total number of nodes in the list.
2. It starts with a length of 0 and traverses the list, incrementing the
length for each node.
3. The `display` function is used to print the list for visualization.
4. In `main`, a few nodes are inserted into the list.
5. The `length` function is called to print the number of nodes in the list.
6. The result will be the length of the list, which is 3 in this case.
7. This operation is useful when determining the size of a linked list.
8. The length of the list can also be used to validate list integrity.
9. This logic helps in scenarios where we need to process nodes based on
their count.
10. The function runs in O(n) time complexity where n is the number of nodes.
*/
if (*head != NULL) {
(*head)->prev = newNode; // Update the previous pointer of the old
head
}
*head = newNode; // Update the head to the new node
}
int main() {
struct Node* head = NULL; // Initialize the head to NULL
insertAtBeginning(&head, 10); // Insert 10 at the beginning
insertAtBeginning(&head, 20); // Insert 20 at the beginning
insertAtBeginning(&head, 30); // Insert 30 at the beginning
display(head); // Display the list
return 0;
}
/* Explanation:
1. The `insertAtBeginning` function inserts a new node at the start of the
doubly linked list.
2. A new node is created and linked to the current head, and its `prev`
pointer is set to NULL.
3. If the list is not empty, the previous head's `prev` pointer is updated to
point to the new node.
4. The head is updated to the new node, making it the first node in the list.
5. The `display` function prints the list from head to tail, with the "prev"
pointers showing the reverse order.
6. In `main`, three nodes are inserted into the list at the beginning.
7. The resulting list is displayed as "30 <-> 20 <-> 10 <-> NULL".
8. This operation adds nodes at the beginning, moving them to the front.
9. It is useful when inserting elements in a deque-like structure.
10. The time complexity of this operation is O(1) since no traversal is
needed.
*/
if (*head == NULL) {
*head = newNode; // If the list is empty, the new node becomes the
head
newNode->prev = NULL;
return;
}
int main() {
struct Node* head = NULL; // Initialize the head to NULL
insertAtEnd(&head, 10); // Insert 10 at the end
insertAtEnd(&head, 20); // Insert 20 at the end
insertAtEnd(&head, 30); // Insert 30 at the end
display(head); // Display the list
return 0;
}
/* Explanation:
1. The `insertAtEnd` function adds a new node at the end of the doubly linked
list.
2. A new node is created, its `next` pointer is set to NULL, and it is linked
to the last node.
3. If the list is empty, the new node becomes the head, and its `prev`
pointer is set to NULL.
4. Otherwise, the program traverses the list to find the last node, then
appends the new node.
5. The `prev` pointer of the new node is set to the last node, maintaining
the doubly linked structure.
6. The `display` function prints the list from head to tail.
7. In `main`, three nodes are inserted into the list at the end.
8. The resulting list is displayed as "10 <-> 20 <-> 30 <-> NULL".
9. This operation ensures nodes are inserted at the end, preserving the list
order.
10. It demonstrates how to grow a doubly linked list dynamically with
efficient insertion at the end.
*/
int main() {
struct Node* head = NULL; // Initialize the head to NULL
insertAtBeginning(&head, 10); // Insert 10 at the beginning
insertAtBeginning(&head, 20); // Insert 20 at the beginning
insertAtBeginning(&head, 30); // Insert 30 at the beginning
display(head); // Display the circular list
return 0;
}
/* Explanation:
1. The `insertAtBeginning` function inserts a node at the beginning of a
circular linked list.
2. If the list is empty, the new node becomes the head and points to itself,
forming a loop.
3. If the list is not empty, the program traverses to the last node and links
it to the new node.
4. The new node’s `next` pointer is set to the head, completing the circular
structure.
5. The `display` function traverses the list starting from the head, printing
each node.
6. In `main`, three nodes are inserted at the beginning of the list.
7. The resulting list is displayed as "30 -> 20 -> 10 -> (back to head)".
8. The program demonstrates how circular references are handled in the list.
9. Circular linked lists are useful for applications like buffering and
round-robin scheduling.
10. The time complexity for this operation is O(1) for inserting at the
beginning of the list.
*/
if (*head == NULL) {
*head = newNode; // If the list is empty, make the new node the head
newNode->next = *head; // The new node points to itself (circular)
} else {
while (temp->next != *head) {
temp = temp->next; // Traverse to the last node
}
temp->next = newNode; // Link the last node to the new node
newNode->next = *head; // The new node points back to the head
}
}
int main() {
struct Node* head = NULL; // Initialize the head to NULL
insertAtEnd(&head, 10); // Insert 10 at the end
insertAtEnd(&head, 20); // Insert 20 at the end
insertAtEnd(&head, 30); // Insert 30 at the end
display(head); // Display the circular list
return 0;
}
/* Explanation:
1. The `insertAtEnd` function adds a new node at the end of a circular linked
list.
2. If the list is empty, the new node becomes the head and points to itself.
3. If the list is not empty, the program traverses to the last node and links
it to the new node.
4. The new node’s `next` pointer is set to the head, ensuring the list
remains circular.
5. The `display` function prints the list starting from the head, then
circles back to the head.
6. In `main`, three nodes are inserted at the end of the list.
7. The resulting list is displayed as "10 -> 20 -> 30 -> (back to head)".
8. This operation efficiently adds nodes to the end of a circular list
without needing a full traversal for insertion.
9. Circular linked lists are useful in applications where traversal needs to
wrap around (e.g., a round-robin scheduler).
10. The time complexity for this operation is O(n) for traversal, but O(1)
for insertion once the last node is found.
*/
int main() {
struct Node* head = NULL; // Initialize the head to NULL
insertAtEnd(&head, 10); // Insert 10 at the end
insertAtEnd(&head, 20); // Insert 20 at the end
insertAtEnd(&head, 30); // Insert 30 at the end
display(head); // Display the list
deleteAtBeginning(&head); // Delete the first node
display(head); // Display the list after deletion
return 0;
}
/* Explanation:
1. The `deleteAtBeginning` function deletes the first node in the circular
linked list.
2. If the list is empty, the function simply returns.
3. If there is only one node, it is freed, and the head is set to NULL.
4. If there are multiple nodes, the program finds the last node and updates
its `next` pointer to the new head.
5. The head is updated to the next node, and the old head node is freed.
6. The `display` function prints the list starting from the head and then
circles back to the head.
7. In `main`, three nodes are inserted at the end of the list, and the first
node is deleted.
8. The resulting list after deletion is displayed as "20 -> 30 -> (back to
head)".
9. Deleting from the beginning of a circular list requires updating the last
node’s pointer.
10. The time complexity of this operation is O(n) due to the traversal to
find the last node.
*/
// Function to delete the node at the beginning of the doubly linked list
void deleteAtBeginning(struct Node** head) {
if (*head == NULL) {
printf("List is empty.\n");
return;
}
struct Node* temp = *head;
if (temp->next == NULL) { // If there is only one node
free(temp);
*head = NULL; // Set the head to NULL
} else {
*head = temp->next; // Move the head to the next node
(*head)->prev = NULL; // Update the new head's previous pointer
free(temp); // Free the old head node
}
}
int main() {
struct Node* head = NULL; // Initialize the head to NULL
insertAtBeginning(&head, 10); // Insert 10 at the beginning
insertAtBeginning(&head, 20); // Insert 20 at the beginning
insertAtBeginning(&head, 30); // Insert 30 at the beginning
display(head); // Display the list
deleteAtBeginning(&head); // Delete the first node
display(head); // Display the list after deletion
return 0;
}
/* Explanation:
1. The `deleteAtBeginning` function removes the first node from a doubly
linked list.
2. If the list is empty, a message is printed, and the function returns.
3. If there is only one node, it is freed, and the head is set to NULL.
4. If there are multiple nodes, the head is updated to the next node.
5. The new head's `prev` pointer is set to NULL.
6. The `display` function prints the list starting from the head node.
7. In `main`, three nodes are inserted at the beginning, and the first node
is deleted.
8. The resulting list after deletion is displayed as "20 <-> 10 <-> NULL".
9. Deleting the first node from a doubly linked list is efficient since the
previous node of the new head is updated.
10. The time complexity of this operation is O(1), making it efficient even
for large lists.
*/
// Function to delete the node at the end of the doubly linked list
void deleteAtEnd(struct Node** head) {
if (*head == NULL) {
printf("List is empty.\n");
return;
}
struct Node* temp = *head;
if (temp->next == NULL) { // If there is only one node
free(temp);
*head = NULL; // Set the head to NULL
} else {
while (temp->next != NULL) { // Traverse to the last node
temp = temp->next;
}
temp->prev->next = NULL; // Update the second-last node’s next
pointer to NULL
free(temp); // Free the last node
}
}
int main() {
struct Node* head = NULL; // Initialize the head to NULL
insertAtEnd(&head, 10); // Insert 10 at the end
insertAtEnd(&head, 20); // Insert 20 at the end
insertAtEnd(&head, 30); // Insert 30 at the end
display(head); // Display the list
deleteAtEnd(&head); // Delete the last node
display(head); // Display the list after deletion
return 0;
}
/* Explanation:
1. The `deleteAtEnd` function removes the last node from a doubly linked
list.
2. If the list is empty, a message is printed, and the function returns.
3. If there is only one node, it is freed, and the head is set to NULL.
4. If there are multiple nodes, the program traverses the list to find the
last node.
5. The second-last node's `next` pointer is set to NULL, and the last node is
freed.
6. The `display` function prints the list from head to tail.
7. In `main`, three nodes are inserted at the end, and the last node is
deleted.
8. The resulting list after deletion is displayed as "10 <-> 20 <-> NULL".
9. This operation efficiently removes the last node from the list, updating
the second-last node's next pointer.
10. The time complexity is O(n) for traversal to find the last node, but the
operation is still efficient for typical use cases. */
int main() {
struct Node* head = NULL;
insertAtEnd(&head, 10);
insertAtEnd(&head, 20);
insertAtEnd(&head, 30);
insertAtEnd(&head, 40);
/* Explanation:
1. The `deleteNode` function deletes the first occurrence of a specific node
(with value `key`).
2. If the node to be deleted is the head node, the head is updated to the
next node, and the old head is freed.
3. If the node to be deleted is not the head, the function traverses the list
to find the node.
4. Once found, the previous node’s `next` pointer is updated to bypass the
node to be deleted.
5. The `display` function prints the list from head to tail.
6. In `main`, a few nodes are inserted, and then a node with value 20 is
deleted.
7. The resulting list after deletion is displayed as "10 -> 30 -> 40 ->
NULL".
8. Deleting a specific node requires traversal of the list, which makes the
time complexity O(n).
9. The logic is useful in applications that require deletion of specific data
from a list.
10. This operation demonstrates typical deletion from a singly linked list.
*/
int main() {
struct Node* head = NULL;
insertAtEnd(&head, 10);
insertAtEnd(&head, 20);
insertAtEnd(&head, 30);
insertAtEnd(&head, 40);
/* Explanation:
1. The `deleteNodeByKey` function deletes a node from the circular linked
list by its value (`key`).
2. If the node to be deleted is the head, the head pointer is updated, and
the last node's `next` pointer is adjusted.
3. If the node is not the head, the program searches for the node to be
deleted.
4. Once found, the previous node's `next` pointer is updated to skip the node
to be deleted.
5. The `display` function prints the list from head to tail, looping back to
the head due to the circular structure.
6. In `main`, nodes are inserted, and a node with value 30 is deleted.
7. The resulting circular list after deletion is displayed as "10 -> 20 -> 40
-> (back to head)".
8. Deleting a node requires handling both the circular nature and node
unlinking carefully.
9. This operation demonstrates efficient node deletion from circular linked
lists.
10. The time complexity for this operation is O(n), where n is the number of
nodes in the list.
*/
// Function to delete the last node from the singly linked list
void deleteAtEnd(struct Node** head) {
if (*head == NULL) {
printf("List is empty.\n");
return;
}
int main() {
struct Node* head = NULL;
insertAtEnd(&head, 10);
insertAtEnd(&head, 20);
insertAtEnd(&head, 30);
insertAtEnd(&head, 40);
/* Explanation:
1. The `deleteAtEnd` function deletes the last node of a singly linked list.
2. If the list is empty, a message is printed and the function returns.
3. If there is only one node, it is freed, and the head is set to NULL.
4. For lists with more than one node, the program traverses to the last node
and updates the second-last node’s `next` pointer to NULL.
5. The `display` function prints the list from head to tail.
6. In `main`, nodes are inserted into the list, and the last node is deleted.
7. The resulting list after deletion is displayed as "10 -> 20 -> 30 ->
NULL".
8. Deleting the last node involves finding the penultimate node and updating
the next pointer.
9. This operation is commonly used when removing elements from the end of a
list.
10. The time complexity for this operation is O(n) because it requires
traversal to find the last node.
*/
free(temp);
}
int main() {
struct Node* head = NULL;
insertAtEnd(&head, 10);
insertAtEnd(&head, 20);
insertAtEnd(&head, 30);
insertAtEnd(&head, 40);
/* Explanation:
1. The `deleteNodeByValue` function deletes a node by its value in a doubly
linked list.
2. If the list is empty, a message is printed, and the function returns.
3. The program traverses the list to find the node with the specified value
(`key`).
4. Once found, the program updates the previous and next pointers of the
surrounding nodes.
5. If the node to be deleted is the head, the head pointer is updated, and
its previous pointer is set to NULL.
6. The `display` function prints the list from head to tail.
7. In `main`, nodes are inserted, and a node with value 30 is deleted.
8. The resulting list after deletion is displayed as "10 <-> 20 <-> 40 <->
NULL".
9. Deletion in a doubly linked list requires careful updating of both the
`next` and `prev` pointers.
10. This operation is O(1) if the node is already located, but O(n) for
searching.
*/
int main() {
struct Node* head = NULL;
insertAtEnd(&head, 10);
insertAtEnd(&head, 20);
insertAtEnd(&head, 30);
insertAtEnd(&head, 40);
/* Explanation:
1. The `reverse` function reverses the circular linked list by reversing the
`next` pointers.
2. The program finds the last node in the list to ensure the circular
structure is preserved.
3. The list is reversed by iterating through the nodes and updating the
`next` pointers.
4. Once reversed, the head is updated, and the last node's `next` pointer is
updated to point to the new head.
5. The `display` function prints the list from head to tail, looping back to
the head.
6. In `main`, the list is displayed before and after the reversal.
7. The resulting list after reversal is displayed as "40 -> 30 -> 20 -> 10 ->
(back to head)".
8. Reversing the list in a circular manner requires updating the head and the
last node’s `next`.
9. The time complexity for this operation is O(n), where n is the number of
nodes in the list.
10. This operation demonstrates reversing a circular linked list efficiently.
*/
// Base cases
if (list1 == NULL) return list2;
if (list2 == NULL) return list1;
int main() {
struct Node* list1 = NULL;
struct Node* list2 = NULL;
insertAtEnd(&list2, 5);
insertAtEnd(&list2, 15);
insertAtEnd(&list2, 25);
printf("List 1: ");
display(list1);
printf("List 2: ");
display(list2);
/* Explanation:
1. The `mergeSortedLists` function merges two sorted singly linked lists into
a single sorted list.
2. The base cases handle the scenario when either list is empty.
3. The function recursively compares the head elements of both lists and
links the smaller element to the result.
4. The merging process ensures that the resulting list is sorted by always
picking the smaller element first.
5. The `display` function prints the merged list from head to tail.
6. In `main`, two sorted lists are created and merged using the function.
7. The merged list is displayed as "5 -> 10 -> 15 -> 20 -> 25 -> 30 -> NULL".
8. This method takes advantage of recursion to merge the two sorted lists.
9. The time complexity of this operation is O(n + m), where n and m are the
lengths of the two lists.
10. This operation demonstrates how to merge two sorted linked lists
efficiently.
*/