From 7fa3e5e626318e34dc61c9f258e34e3760324745 Mon Sep 17 00:00:00 2001 From: Mactavish <maczhanchao@yahoo.com> Date: Mon, 1 May 2023 09:27:41 +0200 Subject: [PATCH] add solution to linked-list --- exercises/linked-list/linked_list.c | 139 +++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 12 deletions(-) diff --git a/exercises/linked-list/linked_list.c b/exercises/linked-list/linked_list.c index 8981740..054dc38 100644 --- a/exercises/linked-list/linked_list.c +++ b/exercises/linked-list/linked_list.c @@ -1,55 +1,170 @@ #include "linked_list.h" +#include <errno.h> +#include <stdlib.h> + +#define FAULT(ERRNO, ERR_CODE) \ + errno = ERRNO; \ + exit(ERR_CODE); + +#define FREE_NODE(NODE) \ + if (NODE) { \ + free(NODE); \ + NODE = NULL; \ + } + struct list_node { - struct list_node *prev, *next; - ll_data_t data; + struct list_node *prev, *next; + ll_data_t data; }; struct list { - struct list_node *first, *last; + struct list_node *first, *last; }; struct list_node *create_node(ll_data_t data) { - // TODO: implement create_node + struct list_node *node; + node = malloc(sizeof(struct list_node)); + if (!node) { + FAULT(ENOMEM, EXIT_FAILURE); + } + node->data = data; + return node; } // constructs a new (empty) list struct list *list_create(void) { - // TODO: implement list_create + struct list *head = malloc(sizeof(struct list)); + // create a dummy node, dummy node should not have any previous node + struct list_node *node = create_node(0); + head->first = node; + head->last = node; + node->prev = node->next = NULL; + return head; } // counts the items on a list size_t list_count(const struct list *list) { - // TODO: implement list_count + size_t count = 0; + if (list->first == list->last) { + return count; + } + struct list_node *dummy = list->first; + struct list_node *node = dummy->next; + while (node != dummy) { + node = node->next; + count++; + } + return count; } // inserts item at back of a list void list_push(struct list *list, ll_data_t item_data) { - // TODO: implement list_push + struct list_node *node = create_node(item_data); + // empty list with a dummy node + if (list->first == list->last) { + list->first->next = node; + list->last = node; + node->prev = node->next = list->first; + } else { + node->prev = list->last; + list->last->next = node; + node->next = list->first; + list->last = node; + } } // removes item from back of a list ll_data_t list_pop(struct list *list) { - // TODO: implement list_pop + // empty list with a dummy node + if (list->first == list->last) { + FAULT(EFAULT, EXIT_FAILURE); + } + struct list_node *last = list->last; + ll_data_t data = last->data; + list->last = last->prev; + last->prev->next = list->first; + FREE_NODE(last); + return data; } // inserts item at front of a list void list_unshift(struct list *list, ll_data_t item_data) { - // TODO: implement list_unshift + // empty list with a dummy node + if (list->first == list->last) { + list_push(list, item_data); + } else { + struct list_node *dummy = list->first, *node = create_node(item_data); + node->next = dummy->next; + node->prev = dummy; + dummy->next->prev = node; + dummy->next = node; + } } // removes item from front of a list ll_data_t list_shift(struct list *list) { - // TODO: implement list_shift + // empty list with a dummy node + if (list->first == list->last) { + FAULT(EFAULT, EXIT_FAILURE); + } else { + struct list_node *dummy = list->first, *node; + node = dummy->next; + ll_data_t data = node->data; + dummy->next = node->next; + // if there are more than one nodes + if (node->next->prev == node) { + node->next->prev = dummy; + } else { + list->last = list->first; + } + FREE_NODE(node); + return data; + } } // deletes a node that holds the matching data void list_delete(struct list *list, ll_data_t data) { - // TODO: implement list_delete + if (list->first == list->last) { + errno = EFAULT; + exit(EXIT_FAILURE); + } else { + struct list_node *dummy = list->first; + struct list_node *node = dummy->next; + while (node != dummy) { + if (node->data == data) { + break; + } + node = node->next; + } + if (node != dummy) { + node->prev->next = node->next; + node->next->prev = node->prev; + if (node == list->last) { + list->last = node->prev; + } + FREE_NODE(node); + } + } } // destroys an entire list // list will be a dangling pointer after calling this method on it void list_destroy(struct list *list) { - // TODO: implement list_destroy + // empty list with a dummy node + if (list->first == list->last) { + FREE_NODE(list->last); + FREE_NODE(list); + } else { + struct list_node *dummy = list->first; + struct list_node *node = dummy->next, *next; + while (node != dummy) { + next = node->next; + FREE_NODE(node); + node = next; + } + FREE_NODE(dummy); + FREE_NODE(list); + } } + -- GitLab