diff options
Diffstat (limited to 'Algorithms/lists.c')
| -rw-r--r-- | Algorithms/lists.c | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/Algorithms/lists.c b/Algorithms/lists.c new file mode 100644 index 0000000..0e73801 --- /dev/null +++ b/Algorithms/lists.c @@ -0,0 +1,225 @@ +/* + * Linked lists implementation +*/ + +#include <stdlib.h> +#include <string.h> + +#include "lists.h" + +/* SINGLY LINKED LIST */ + +void list_init(List *list, void (*destroy)(void *data)) +{ + list->size = 0; + list->destroy = destroy; + list->head = NULL; + list-tail = NULL; + + return; +} + +void list_destroy(List *list) +{ + void *data = NULL; + + while (list_size(list) > 0) { + /* list_rem_next removes head's element if passed NULL */ + if (list_rem_next(list, NULL, (void **)&data) == 0 && + list->destroy != NULL) + list->destroy(data); + } + + memset(list, 0, sizeof(List)); + return; +} + +int list_ins_next(List *list, ListElmt *element, const void *data) +{ + ListElmt *new_element; + + if ((new_element = (ListElmt *)malloc(sizeof(ListElmt))) == NULL) + return -1; + + new_element->data = (void *)data; + + if (element == NULL) { + if (list_size(list) == 0) + list->tail = new_element; + + new_element->next = list->head; + list->head = new_element; + } else { + if (element->next == NULL) + list->tail = new_element; + + new_element->next = element->next; + element->next = new_element + } + + list->size++; + return 0; +} + +int list_rem_next(List *list, ListElmt *element, void **data) { + ListElmt *old_element; + + if (list_size(list) == 0) + return -1; + + if (element == NULL) { + *data = list->head->data; + old_element = list->head; + list->head = list->head->next; + + if (list_size(list) == 1) + list->tail = NULL; + + } else { + if (element->next == NULL) + return -1; + + *data = element->next->data; + old_element = element->next; + element->next = element->next->next; + + if (element->next == NULL) + list->tail = element; + } + + free(old_element); + list->size--; + return 0; +} + +/* SINGLY LINKED LIST -- END */ + +/* DOUBLY LINKED LIST */ + +void dlist_init(struct DList *list, void (*destroy)(void *data)) { + + /* Initialize list */ + list->size = 0; + list->destroy = destroy; + list->head = NULL; + list->tail = NULL; + return; +} + +void dlist_destroy(struct DList *list) { + void *data; + + /* Remove elements */ + while (dlist_size(list) > 0) { + if (dlist_remove(list, dlist_tail(list), (void **)&data) == 0 + && list->destroy != NULL) + list->destroy(data); + } + + /* clear list struct just in case */ + memset(list, 0, sizeof(DList)); + return; +} + +int dlist_ins_next(struct DList *list, + struct DListElmt *element, + const void *data) +{ + struct DListElmt *new; + + /* No NULL elements allowed */ + if (element == NULL && dlist_size(list) != 0) + return -1; + + if ((new = (struct DListElmt *)malloc(sizeof(struct DListElmt))) == NULL) + return -1; + + new->data = (void *)data; + + if (dlist_size(list) == 0) { + list->head = new; + list->head->prev = NULL; + list->head->next = NULL; + list->tail = new; + } else { + new->next = element->next; + new->prev = element; + + if (new->next == NULL) + list->tail = new; + else + new->next->prev = new; + + element->next = new; + } + + list->size++; + return 0 +} + +int dlist_ins_prev(struct DList *list, + struct DListElmt *element, + const void *data) +{ + struct DListElmt *new; + + /* No NULL elements allowed */ + if (element == NULL && dlist_size(list) != 0) + return -1; + + if ((new = (struct DListElmt *)malloc(sizeof(struct DListElmt))) == NULL) + return -1; + + new->data = (void *)data; + + if (dlist_size(list) == 0) { + /* insert on head */ + list->head = new; + list->head->prev = NULL; + list->head->next = NULL; + list->tail = new; + } else { + new->next = element; + new->prev = element->prev; + + if (new->prev == NULL) + list->head = new; + else + element->prev->next = new; + + element->prev = new; + } + + list_size++; + return 0; +} + +int dlist_remove(struct DList *list, struct DListElmt *element, void **data) +{ + /* No NULL element allowed or removal from empty */ + if (element == NULL || dlist_size(list == 0)) + return -1; + + /* Remove element */ + *data = element->data; + + if (element == list->head) { + list->head = element->next; + + if (list->head == NULL) + list->tail = NULL; + else + list->head->prev = NULL; + } else { + element->prev->next = element->next; + + if (element->next == NULL) + list->tail = element->prev; + else + element->next->prev = element->prev; + } + + free(element); + list->size--; + return 0; +} |
