summaryrefslogtreecommitdiff
path: root/Algorithms/lists.c
diff options
context:
space:
mode:
Diffstat (limited to 'Algorithms/lists.c')
-rw-r--r--Algorithms/lists.c225
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;
+}