From 8c290a2e7c564635b67765b5497683cd49d1114c Mon Sep 17 00:00:00 2001 From: Andrew Miner Date: Sat, 9 Mar 2024 18:20:22 -0700 Subject: [PATCH] Add initial version of LinkedList C module --- linkedlist.c | 234 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 linkedlist.c diff --git a/linkedlist.c b/linkedlist.c new file mode 100644 index 0000000..0b489fe --- /dev/null +++ b/linkedlist.c @@ -0,0 +1,234 @@ +#include +#include +#include + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Type Definitions //////////////////////////////////////////////////////////////////////////////// + +typedef struct LinkedListNode LinkedListNode; + +struct LinkedListNode { + int value; + LinkedListNode *next; +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Memory Management /////////////////////////////////////////////////////////////////////////////// + +// Create a new linked list with a given value +LinkedListNode* LinkedList_new(int value) { + LinkedListNode *head = malloc(sizeof(LinkedListNode)); + head->value = value; + head->next = NULL; + return head; +} + +// Free all the nodes in a linked list +LinkedListNode* LinkedList_free(LinkedListNode *head) { + if (head == NULL) return NULL; + + LinkedListNode *current = head; + LinkedListNode *toDelete = NULL; + + while (current != NULL) { + toDelete = current; + current = current->next; + free(toDelete); + } + + return NULL; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Mutation //////////////////////////////////////////////////////////////////////////////////////// + +// Add a value to the start of the linked list +LinkedListNode* LinkedList_prepend(LinkedListNode *head, int value) { + LinkedListNode *newHead = LinkedList_new(value); + newHead->next = head; + return newHead; +} + +// Add a value to the end of the linked list +LinkedListNode* LinkedList_append(LinkedListNode *head, int value) { + if (head == NULL) return NULL; + + LinkedListNode *current = head; + while (current->next != NULL) { + current = current->next; + } + + current->next = LinkedList_new(value); + + return head; +} + +// Remove a value from the start of the linked list +LinkedListNode* LinkedList_pull(LinkedListNode *head, int *shiftedValue) { + if (head == NULL) return NULL; + + *shiftedValue = head->value; + + LinkedListNode *toDelete = head; + head = head->next; + toDelete->next = NULL; + LinkedList_free(toDelete); + + return head; +} + +// Remove a value from the end of the linked list +LinkedListNode* LinkedList_pop(LinkedListNode *head, int *poppedValue) { + if (head == NULL) return NULL; + + LinkedListNode *current = head; + LinkedListNode *prior = NULL; + while (current->next != NULL) { + prior = current; + current = current->next; + } + + *poppedValue = current->value; + + if (prior != NULL) { + prior->next = LinkedList_free(current); + } else { + head = LinkedList_free(head); + } + + return head; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Query /////////////////////////////////////////////////////////////////////////////////////////// + +// Determines whether a value exists in the list +bool LinkedList_contains(LinkedListNode *head, int value) { + LinkedListNode *current = head; + while (current != NULL) { + if (current->value == value) return true; + current = current->next; + } + + return false; +} + +// Determines the number of nodes in the list +int LinkedList_length(LinkedListNode *head) { + int result = 0; + LinkedListNode *current = head; + while (current != NULL) { + current = current->next; + result++; + } + + return result; +} + +// Prints the list to the console +void LinkedList_print(LinkedListNode *head) { + LinkedListNode *current = head; + while (current != NULL) { + printf("(%d)->", current->value); + current = current->next; + } + printf("NULL"); +} + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Tests /////////////////////////////////////////////////////////////////////////////////////////// + +LinkedListNode *buildTest() { + LinkedListNode *head = LinkedList_new(42); + head = LinkedList_append(head, 43); + head = LinkedList_append(head, 44); + return head; +} + +void test_prepend() { + printf("Running test: prepend\n"); + LinkedListNode *head = LinkedList_new(42); + head = LinkedList_prepend(head, 43); + head = LinkedList_prepend(head, 44); + LinkedList_print(head); printf(" should be (44)->(43)->(42)->NULL\n"); + + head = LinkedList_free(head); + printf("\n"); +} + +void test_append() { + printf("Running test: append\n"); + LinkedListNode *head = buildTest(); + LinkedList_print(head); printf(" should be (42)->(43)->(44)->NULL\n"); + + head = LinkedList_free(head); + printf("\n"); +} + +void test_pull() { + printf("Running test: pull\n"); + LinkedListNode *head = buildTest(); + + int value = 0; + head = LinkedList_pull(head, &value); + printf("%d should be 42\n", value); + LinkedList_print(head); printf(" should be (43)->(44)->NULL\n"); + head = LinkedList_pull(head, &value); + printf("%d should be 43\n", value); + LinkedList_print(head); printf(" should be (44)->NULL\n"); + head = LinkedList_pull(head, &value); + printf("%d should be 44\n", value); + LinkedList_print(head); printf(" should be NULL\n"); + + head = LinkedList_free(head); + printf("\n"); +} + +void test_pop() { + printf("Running test: pop\n"); + LinkedListNode *head = buildTest(); + + int value = 0; + head = LinkedList_pop(head, &value); + printf("%d should be 44\n", value); + LinkedList_print(head); printf(" should be (42)->(43)->NULL\n"); + head = LinkedList_pop(head, &value); + printf("%d should be 43\n", value); + LinkedList_print(head); printf(" should be (42)->NULL\n"); + head = LinkedList_pop(head, &value); + printf("%d should be 42\n", value); + LinkedList_print(head); printf(" should be NULL\n"); + + head = LinkedList_free(head); + printf("\n"); +} + +void test_contains() { + printf("Running test: contains\n"); + LinkedListNode *head = buildTest(); + + printf("%s should be true\n", LinkedList_contains(head, 43) ? "true" : "false"); + printf("%s should be false\n", LinkedList_contains(head, 90) ? "true" : "false"); + + head = LinkedList_free(head); + printf("\n"); +} + +void test_length() { + printf("Running test: length\n"); + LinkedListNode *head = buildTest(); + + printf("%d should be 3\n", LinkedList_length(head)); + + head = LinkedList_free(head); + printf("\n"); +} + +int main() { + test_prepend(); + test_append(); + test_pull(); + test_pop(); + test_contains(); + test_length(); +}