// ========== [ LAB ASSIGNMENT - 3 ] ==========
// +--------------------------+
// | Name: SAKSHAM MITTAL |
// | Roll Number: 102319061 |
// +--------------------------+
// ============================================
// IMPORTANT
// --------------------------------------------
// Each function of the form: void container_ass3_quesN() { ... }
// is to be treated as an isolated container for Assignment - 3, Question - N.
// --------------------------------------------
// COMPILATION
// --------------------------------------------
// This code has been developed and tested with the following gcc version:
// gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
// --------------------------------------------
// COMMAND USED FOR COMPILATION (Make sure you have created a directory named bin before compiling)
// --------------------------------------------
// gcc -Wall labass3_102319061.c -O3 -o ./bin/labass3 && ./bin/labass3
// --------------------------------------------
// The platform on which the code has been developed and tested:
// Linux 5.15.153.1-microsoft-standard-WSL2 #1 SMP Fri Mar 29 23:14:13 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux
// Used for compilation: gcc -Wall labass3_102319061.c -O3 -o ./bin/labass3 && ./bin/labass3
#include <stdio.h>
#include <stdlib.h>
// ################# SINGLY LINKED LIST #################
typedef struct singlyLinkedNode {
struct singlyLinkedNode* next;
int data;
} singlyLinkedNode;
typedef struct singlyLinkedList {
struct singlyLinkedNode* first;
int numNodes;
} singlyLinkedList;
singlyLinkedNode* singlyLinked_createNode() {
singlyLinkedNode* node = (singlyLinkedNode*)malloc(sizeof(singlyLinkedNode));
node->next = NULL;
return node;
}
singlyLinkedList* singlyLinked_createList() {
singlyLinkedList* list = (singlyLinkedList*)malloc(sizeof(singlyLinkedList));
list->first = NULL;
list->numNodes = 0;
return list;
}
void singlyLinked_addNodeToTail(singlyLinkedList* list, singlyLinkedNode* node) {
// If list is empty
if ((list->first == NULL)||(list->numNodes == 0)) {
list->first = node;
list->numNodes++;
return;
}
singlyLinkedNode* nodeUnderConsideration = list->first;
while (1) {
if (nodeUnderConsideration->next == NULL) {
// This is the last node
nodeUnderConsideration->next = node;
break;
} else {
nodeUnderConsideration = nodeUnderConsideration->next;
}
}
list->numNodes++;
}
void singlyLinked_addNodeToHead(singlyLinkedList* list, singlyLinkedNode* node) {
node->next = list->first;
list->first = node;
list->numNodes++;
}
void singlyLinked_popNodeFromHead(singlyLinkedList* list) {
// The removed node can be freed from the heap for now this has been skipped.
// Leaving it to the user to decide whether they use the removed node in a
// different list or free() it.
list->first = list->first->next;
list->numNodes--;
}
void singlyLinked_popNodeFromTail(singlyLinkedList* list) {
// Do nothing if the list is already empty
if ((list->first == NULL)||(list->numNodes == 0)) {
return;
}
// If list contains only one node
if (list->first->next == NULL) {
list->first = NULL;
list->numNodes--;
return;
}
singlyLinkedNode* nodeUnderConsideration = list->first;
singlyLinkedNode* prevNode = NULL;
while (1) {
if (nodeUnderConsideration->next == NULL) {
// Reached last node
prevNode->next = NULL;
list->numNodes--;
break;
} else {
prevNode = nodeUnderConsideration;
nodeUnderConsideration = nodeUnderConsideration->next;
}
}
}
void singlyLinked_printList(singlyLinkedList* list) {
printf("-------------------------------\n");
printf("Singly Linked List: %d nodes\n", list->numNodes);
if ((list->first == NULL)||(list->numNodes == 0)) { return; }
singlyLinkedNode* nodeUnderConsideration = list->first;
while (1) {
if (nodeUnderConsideration->next == NULL) {
printf("%d\n", nodeUnderConsideration->data);
printf("-------------------------------\n");
break;
} else {
printf("%d -> ", nodeUnderConsideration->data);
nodeUnderConsideration = nodeUnderConsideration->next;
}
}
}
void singlyLinked_insertNodeAtIndex(singlyLinkedList* list, singlyLinkedNode* node, int toInsertIndex) {
// empty list
if ((list->first == NULL)||(list->numNodes == 0)) {
list->first = node;
list->numNodes++;
return;
}
// invalid index, exit silently
// this check can be removed if you want to strictly not use list->numNodes
if (toInsertIndex >= list->numNodes) { return; }
singlyLinkedNode* nodeUnderConsideration = list->first;
int index = 0;
while (index < toInsertIndex - 1) {
nodeUnderConsideration = nodeUnderConsideration->next;
index++;
}
node->next = nodeUnderConsideration->next;
nodeUnderConsideration->next = node;
list->numNodes++;
}
void singlyLinked_popNodeAtIndex(singlyLinkedList* list, int toRemoveIndex) {
// empty list
if ((list->first == NULL)||(list->numNodes == 0)) { return; }
// invalid index, exit silently
// this check can be removed if you want to strictly not use list->numNodes
if (toRemoveIndex >= list->numNodes) { return; }
singlyLinkedNode* nodeUnderConsideration = list->first;
singlyLinkedNode* prevNode = NULL;
int index = 0;
while (index < toRemoveIndex) {
prevNode = nodeUnderConsideration;
nodeUnderConsideration = nodeUnderConsideration->next;
index++;
}
prevNode->next = nodeUnderConsideration->next;
list->numNodes--;
free(nodeUnderConsideration);
}
// Element found: index (node count starts from 0), Element not found: -1
int singlyLinked_linearSearch(singlyLinkedList* list, int toSearch) {
if ((list->first == NULL)||(list->numNodes == 0)) { return -1; }
singlyLinkedNode* nodeUnderConsideration = list->first;
int index = 0, returnIndex = -1;
while (nodeUnderConsideration->next != NULL) {
if (nodeUnderConsideration->data == toSearch) {
returnIndex = index;
break;
} else {
nodeUnderConsideration = nodeUnderConsideration->next;
index++;
}
}
return returnIndex;
}
// ################# DOUBLE LINKED LIST #################
typedef struct doublyLinkedNode {
struct doublyLinkedNode* prev;
struct doublyLinkedNode* next;
int data;
} doublyLinkedNode;
typedef struct doublyLinkedList {
struct doublyLinkedNode* first;
struct doublyLinkedNode* last;
int numNodes;
} doublyLinkedList;
doublyLinkedNode* doublyLinked_createNode(int data) {
doublyLinkedNode* node = (doublyLinkedNode*)malloc(sizeof(doublyLinkedNode));
node->next = NULL;
node->prev = NULL;
node->data = data;
return node;
}
doublyLinkedList* doublyLinked_createList() {
doublyLinkedList* list = (doublyLinkedList*)malloc(sizeof(doublyLinkedList));
list->first = NULL;
list->last = NULL;
list->numNodes = 0;
return list;
}
void doublyLinked_pushBack(doublyLinkedList* list, int data) {
doublyLinkedNode* node = doublyLinked_createNode(data);
if ((list->first == NULL)||(list->numNodes == 0)||(list->last == NULL)) {
list->first = node;
list->last = node;
list->numNodes++;
return;
}
list->last->next = node;
node->prev = list->last;
list->last = node;
list->numNodes++;
}
void doublyLinked_popBack(doublyLinkedList* list) {
// list is empty, nothing to do
if ((list->first == NULL)||(list->numNodes == 0)||(list->last == NULL)) { return; }
list->last->prev->next = NULL;
list->last = list->last->prev;
list->numNodes--;
}
void doublyLinked_pushFront(doublyLinkedList* list, int data) {
doublyLinkedNode* node = doublyLinked_createNode(data);
if ((list->first == NULL)||(list->numNodes == 0)||(list->last == NULL)) {
list->first = node;
list->last = node;
list->numNodes++;
return;
}
list->first->prev = node;
node->next = list->first;
list->first = node;
list->numNodes++;
}
void doublyLinked_popFront(doublyLinkedList* list) {
// list is empty, nothing to do
if ((list->first == NULL)||(list->numNodes == 0)||(list->last == NULL)) { return; }
list->first->next->prev = NULL;
list->first = list->first->next;
list->numNodes--;
}
void doublyLinked_insertAtIndex(doublyLinkedList* list, int data, int toInsertIndex) {
// invalid index
if (toInsertIndex >= list->numNodes) { return; }
doublyLinkedNode* node = doublyLinked_createNode(data);
if ((list->first == NULL)||(list->numNodes == 0)||(list->last == NULL)) {
list->first = node;
list->last = node;
list->numNodes++;
return;
}
int index = 0;
doublyLinkedNode* nodeUnderConsideration = list->first;
while (index < toInsertIndex - 1) {
nodeUnderConsideration = nodeUnderConsideration->next;
index++;
}
node->next = nodeUnderConsideration->next;
nodeUnderConsideration->next->prev = node;
nodeUnderConsideration->next = node;
node->prev = nodeUnderConsideration;
list->numNodes++;
}
void doublyLinked_popAtIndex(doublyLinkedList* list, int toRemoveIndex) {
// list is empty, nothing to do
if ((list->first == NULL)||(list->numNodes == 0)||(list->last == NULL)) { return; }
// invalid index
if (toRemoveIndex >= list->numNodes) { return; }
int index = 0;
doublyLinkedNode* nodeUnderConsideration = list->first;
while (index < toRemoveIndex) {
nodeUnderConsideration = nodeUnderConsideration->next;
index++;
}
nodeUnderConsideration->prev->next = nodeUnderConsideration->next;
nodeUnderConsideration->next->prev = nodeUnderConsideration->prev;
list->numNodes--;
free(nodeUnderConsideration);
}
void doublyLinked_printList(doublyLinkedList* list) {
printf("-------------------------------\n");
printf("Doubly Linked List: %d nodes | first: %p last: %p\n", list->numNodes, list->first, list->last);
if ((list->first == NULL)||(list->numNodes == 0)||(list->last == NULL)) {
printf("-------------------------------\n");
return;
}
doublyLinkedNode* nodeUnderConsideration = list->first;
while (nodeUnderConsideration->next != NULL) {
printf("%d <-> ", nodeUnderConsideration->data);
nodeUnderConsideration = nodeUnderConsideration->next;
}
printf("%d\n", nodeUnderConsideration->data);
printf("-------------------------------\n");
}
// ################# CIRCULAR DOUBLE LINKED LIST #################
typedef struct circularDoublyLinkedNode {
struct circularDoublyLinkedNode* prev;
struct circularDoublyLinkedNode* next;
int data;
} circularDoublyLinkedNode;
typedef struct circularDoublyLinkedList {
struct circularDoublyLinkedNode* first;
struct circularDoublyLinkedNode* last;
int numNodes;
} circularDoublyLinkedList;
circularDoublyLinkedNode* circular_createNode(int data) {
circularDoublyLinkedNode* node = (circularDoublyLinkedNode*)malloc(sizeof(circularDoublyLinkedNode));
node->prev = NULL;
node->next = NULL;
node->data = data;
return node;
}
circularDoublyLinkedList* circular_createList() {
circularDoublyLinkedList* list = (circularDoublyLinkedList*)malloc(sizeof(circularDoublyLinkedList));
list->first = NULL;
list->last = NULL;
list->numNodes = 0;
return list;
}
void circular_pushBack(circularDoublyLinkedList* list, int data) {
circularDoublyLinkedNode* node = circular_createNode(data);
// Empty List
if ((list->first == NULL)||(list->last == NULL)||(list->numNodes == 0)) {
list->first = node;
list->last = node;
node->next = node;
node->prev = node;
list->numNodes++;
return;
}
list->last->next = node;
node->prev = list->last;
list->last = node;
node->next = list->first;
list->first->prev = node;
list->numNodes++;
}
void circular_popBack(circularDoublyLinkedList* list) {
// Empty List
if ((list->first == NULL)||(list->last == NULL)||(list->numNodes == 0)) { return; }
// List has only one element
if ((list->first == list->last)||(list->numNodes == 1)) {
list->first = NULL;
list->last = NULL;
list->numNodes = 0;
return;
}
list->last->prev->next = list->first;
list->first->prev = list->last->prev;
list->last = list->last->prev;
list->numNodes--;
return;
}
void circular_pushFront(circularDoublyLinkedList* list, int data) {
circularDoublyLinkedNode* node = circular_createNode(data);
// Empty List
if ((list->first == NULL)||(list->last == NULL)||(list->numNodes == 0)) {
list->first = node;
list->last = node;
node->next = node;
node->prev = node;
list->numNodes++;
return;
}
list->last->next = node;
node->prev = list->last;
node->next = list->first;
list->first->prev = node;
list->first = node;
list->numNodes++;
}
void circular_popFront(circularDoublyLinkedList* list) {
// Empty List
if ((list->first == NULL)||(list->last == NULL)||(list->numNodes == 0)) { return; }
// List has only one element
if ((list->first == list->last)||(list->numNodes == 1)) {
list->first = NULL;
list->last = NULL;
list->numNodes = 0;
return;
}
list->last->next = list->first->next;
list->first->next->prev = list->last;
list->first = list->first->next;
list->numNodes--;
}
void circular_insertAtIndex(circularDoublyLinkedList* list, int data, int toInsertIndex) {
// Resolve index
while (toInsertIndex >= list->numNodes) {
toInsertIndex = toInsertIndex - list->numNodes;
}
circularDoublyLinkedNode* node = circular_createNode(data);
// Empty List
if ((list->first == NULL)||(list->last == NULL)||(list->numNodes == 0)) {
list->first = node;
list->last = node;
node->next = node;
node->prev = node;
list->numNodes++;
return;
}
int index = 0;
circularDoublyLinkedNode* nodeUnderConsideration = list->first;
while (index < toInsertIndex - 1) {
nodeUnderConsideration = nodeUnderConsideration->next;
index++;
}
node->next = nodeUnderConsideration->next;
nodeUnderConsideration->next->prev = node;
nodeUnderConsideration->next = node;
node->prev = nodeUnderConsideration;
list->numNodes++;
}
void circular_popAtIndex(circularDoublyLinkedList* list, int toRemoveIndex) {
// Resolve index
while (toRemoveIndex >= list->numNodes) {
toRemoveIndex = toRemoveIndex - list->numNodes;
}
// Empty List
if ((list->first == NULL)||(list->last == NULL)||(list->numNodes == 0)) { return; }
int index = 0;
circularDoublyLinkedNode* nodeUnderConsideration = list->first;
while (index < toRemoveIndex + 1) {
nodeUnderConsideration = nodeUnderConsideration->next;
index++;
}
nodeUnderConsideration->prev->next = nodeUnderConsideration->next;
nodeUnderConsideration->next->prev = nodeUnderConsideration->prev;
list->numNodes--;
free(nodeUnderConsideration);
}
void circular_printList(circularDoublyLinkedList* list) {
printf("-------------------------------\n");
printf("Circular Doubly Linked List: %d nodes | first: %p last: %p\n", list->numNodes, list->first, list->last);
if ((list->first == NULL)||(list->last == NULL)||(list->numNodes == 0)) { return; }
circularDoublyLinkedNode* nodeUnderConsideration = list->first;
printf("... -> ");
while (nodeUnderConsideration->next != list->first) {
printf("%d <-> ", nodeUnderConsideration->data);
nodeUnderConsideration = nodeUnderConsideration->next;
}
printf("%d <- ...\n", nodeUnderConsideration->data);
printf("-------------------------------\n");
}
// ################# USAGE #################
void container_ass3_ques1() {
printf("Question - 1, SINGLY LINKED LIST\n");
printf("-------------------------------\n");
printf("Initial Singly Linked List (nodes added to tail):\n");
singlyLinkedList* list = singlyLinked_createList();
for (int i = 0; i < 10; i++) {
singlyLinkedNode* node = singlyLinked_createNode();
node->data = i + 100;
singlyLinked_addNodeToTail(list, node);
}
singlyLinked_printList(list);
printf("Adding a node at the head.\n");
singlyLinkedNode* myHeadNode = singlyLinked_createNode();
myHeadNode->data = 69;
singlyLinked_addNodeToHead(list, myHeadNode);
singlyLinked_printList(list);
printf("Removing a node from the tail.\n");
singlyLinked_popNodeFromTail(list);
singlyLinked_printList(list);
printf("Removing a node from the head.\n");
singlyLinked_popNodeFromHead(list);
singlyLinked_printList(list);
printf("Inserting a node after 6 nodes.\n");
singlyLinkedNode* myOtherNode = singlyLinked_createNode();
myOtherNode->data = 42;
singlyLinked_insertNodeAtIndex(list, myOtherNode, 6);
singlyLinked_printList(list);
printf("Performing linear search for node with data = 42\n");
int foundIndex = singlyLinked_linearSearch(list, 42);
if (foundIndex == -1) {
printf("No such node found.\n");
} else {
printf("Node found at index: %d i.e. (%d-th node)\n", foundIndex, foundIndex + 1);
}
printf("-------------------------------\n");
printf("Removing the above mentioned node.\n");
singlyLinked_popNodeAtIndex(list, 6);
singlyLinked_printList(list);
}
void container_ass3_ques2() {
printf("Question - 2, DOUBLY LINKED LIST\n");
printf("-------------------------------\n");
printf("Initial Doubly Linked List (nodes added to tail):\n");
doublyLinkedList* list = doublyLinked_createList();
for (int i = 0; i < 10; i++) {
doublyLinked_pushBack(list, 100 + i);
}
doublyLinked_printList(list);
printf("Adding a node at the head.\n");
doublyLinked_pushFront(list, 42);
doublyLinked_printList(list);
printf("Removing a node from the tail.\n");
doublyLinked_popBack(list);
doublyLinked_printList(list);
printf("Removing a node from the head.\n");
doublyLinked_popFront(list);
doublyLinked_printList(list);
printf("Inserting a node after 6 nodes.\n");
doublyLinked_insertAtIndex(list, 69, 6);
doublyLinked_printList(list);
printf("Removing the above mentioned node.\n");
doublyLinked_popAtIndex(list, 6);
doublyLinked_printList(list);
}
void container_ass3_ques3() {
printf("Question - 3, CIRCULAR DOUBLY LINKED LIST\n");
printf("-------------------------------\n");
printf("Initial Circular Doubly Linked List (nodes added to tail):\n");
circularDoublyLinkedList* list = circular_createList();
for (int i = 0; i < 10; i++) {
circular_pushBack(list, 100 + i);
}
circular_printList(list);
printf("Adding a node at the head.\n");
circular_pushFront(list, 42);
circular_printList(list);
printf("Removing a node from the tail.\n");
circular_popBack(list);
circular_printList(list);
printf("Removing a node from the head.\n");
circular_popFront(list);
circular_printList(list);
printf("Inserting a node after 6 nodes.\n");
circular_insertAtIndex(list, 69, 6);
circular_printList(list);
printf("Inserting a node after 14 nodes.(More than one round around the list)\n");
circular_insertAtIndex(list, 53, 14);
circular_printList(list);
printf("Removing the above mentioned node.\n");
circular_popAtIndex(list, 14);
circular_printList(list);
}
int main() {
printf("========= [ SAKSHAM MITTAL - 102319061 ] =========\n");
container_ass3_ques3();
return 0;
}
```om the tail.\n");
circular_popBack(list);
circular_printList(list);
printf("Removing a node from the head.\n");
circular_popFront(list);
circular_printList(list);
printf("Inserting a node after 6 nodes.\n");
circular_insertAtIndex(list, 69, 6);
circular_printList(list);
printf("Inserting a node after 14 nodes.(More than one round around the list)\n");
circular_insertAtIndex(list, 53, 14);
circular_printList(list);
printf("Removing the above mentioned node.\n");
circular_popAtIndex(list, 14);
circular_printList(list);
}
int main() {
printf("========= [ SAKSHAM MITTAL - 102319061 ] =========\n");
container_ass3_ques3();
return 0;
}