From ea56a08981871db66523cdcddc3792a371280beb Mon Sep 17 00:00:00 2001 From: Ben Blazak Date: Fri, 6 Jul 2012 00:35:01 -0700 Subject: [PATCH] added linked lists in lib/data-types --- src/lib/data-types.h | 1 + src/lib/data-types/linked-list.c | 156 +++++++++++++++++++++++++++++++ src/lib/data-types/linked-list.h | 86 +++++++++++++++++ 3 files changed, 243 insertions(+) create mode 100644 src/lib/data-types/linked-list.c create mode 100644 src/lib/data-types/linked-list.h diff --git a/src/lib/data-types.h b/src/lib/data-types.h index 453dca1..434cc97 100644 --- a/src/lib/data-types.h +++ b/src/lib/data-types.h @@ -12,6 +12,7 @@ #include #include + #include "data-types/linked-list.h" #define bool _Bool #define true ((bool)1) diff --git a/src/lib/data-types/linked-list.c b/src/lib/data-types/linked-list.c new file mode 100644 index 0000000..ec14c1e --- /dev/null +++ b/src/lib/data-types/linked-list.c @@ -0,0 +1,156 @@ +/* ---------------------------------------------------------------------------- + * linked list + * ---------------------------------------------------------------------------- + * Copyright (c) 2012 Ben Blazak + * Released under The MIT License (MIT) (see "license.md") + * Project located at + * ------------------------------------------------------------------------- */ + + +#include +#include "lib/data-types.h" + +#include "linked-list.h" + + +// convenience macros (undefined later) +#define _NEW_STRUCT_POINTER(type, name) \ + struct type * name = (struct type *) malloc(sizeof(struct type)) + + +struct linked_list * linked_list_new(void) { + _NEW_STRUCT_POINTER(linked_list, list); + if (!list) return NULL; + + list->head = NULL; + list->tail = NULL; + + list->number_of_elements = 0; + return list; +} + +struct linked_list * linked_list_add_head( + struct linked_list * list, + LINKED_LIST_DATA_TYPE data ) { + + _NEW_STRUCT_POINTER(linked_list_node, node); + if (!node) return NULL; + + node->data = data; + node->next = list->head; + list->head = node; + if (list->number_of_elements == 0) + list->tail = node; + + list->number_of_elements++; + return list; +} + +struct linked_list * linked_list_add_tail( + struct linked_list * list, + LINKED_LIST_DATA_TYPE data ) { + + _NEW_STRUCT_POINTER(linked_list_node, node); + if (!node) return NULL; + + node->data = data; + node->next = NULL; + if (list->number_of_elements == 0) + list->head = node; + else + list->tail->next = node; + list->tail = node; + + list->number_of_elements++; + return list; +} + +LINKED_LIST_DATA_TYPE linked_list_pop_head(struct linked_list * list) { + if (list->number_of_elements == 0) + return 0; + + struct linked_list_node node = { + .data = list->head->data, + .next = list->head->next + }; + + free(list->head); + + if (list->number_of_elements == 1) { + list->head = NULL; + list->tail = NULL; + } else { + list->head = node.next; + } + + list->number_of_elements--; + return node.data; +} + +// note: this function is inefficient for singly linked lists: it has O(n) time +// instead of O(1) time like most of the other functions. but it's not needed +// for implementing stacks or queues, so i don't anticipate it being used all +// that much. it's here for completeness. +LINKED_LIST_DATA_TYPE linked_list_pop_tail(struct linked_list * list) { + if (list->number_of_elements == 0) + return 0; + + struct linked_list_node node = { + .data = list->tail->data, + .next = list->tail->next + }; + + free(list->tail); + + if (list->number_of_elements == 1) { + list->head = NULL; + list->tail = NULL; + } else { + list->tail = list->head; + for (uint8_t i=2; i<(list->number_of_elements); i++) + list->tail = list->tail->next; + list->tail->next = NULL; + } + + list->number_of_elements--; + return node.data; +} + +LINKED_LIST_DATA_TYPE linked_list_read( + struct linked_list * list, + uint8_t position ) { + + if (position < 1 || position > (list->number_of_elements)) + return 0; + + struct linked_list_node * node = list->head; + for (uint8_t i=1; inext; + + return node->data; +} + +struct linked_list * linked_list_copy(struct linked_list * list) { + _NEW_STRUCT_POINTER(linked_list, copy); + + for (uint8_t i=1; i<=(list->number_of_elements); i++) + linked_list_add_tail(copy, linked_list_read(list, i)); + + return copy; +} + + +// note: this is implemented inefficiently (using ...pop_head(), which does +// extra work). but that makes things simpler, and i don't anticipate using it +// all that often. +void linked_list_free(struct linked_list * list) { + while ((list->number_of_elements) > 0) + linked_list_pop_head(list); + + free(list); +} + + +// convenience macros (undefined here) +#undef _NEW_STRUCT_POINTER + diff --git a/src/lib/data-types/linked-list.h b/src/lib/data-types/linked-list.h new file mode 100644 index 0000000..9a918e7 --- /dev/null +++ b/src/lib/data-types/linked-list.h @@ -0,0 +1,86 @@ +/* ---------------------------------------------------------------------------- + * linked list : exports + * + * Includes aliases to treat the list as a queue or stack. + * ---------------------------------------------------------------------------- + * Copyright (c) 2012 Ben Blazak + * Released under The MIT License (MIT) (see "license.md") + * Project located at + * ------------------------------------------------------------------------- */ + + +#ifndef LINKED_LIST_h + #define LINKED_LIST_h + + #include "lib/data-types.h" + + + // default list data type + #ifndef LINKED_LIST_DATA_TYPE + #define LINKED_LIST_DATA_TYPE uint8_t + #endif + + + // structs + struct linked_list_node { + LINKED_LIST_DATA_TYPE data; + struct linked_list_node * next; + }; + + struct linked_list{ + uint8_t number_of_elements; + struct linked_list_node * head; + struct linked_list_node * tail; + }; + + // functions + struct linked_list * linked_list_new(void); + struct linked_list * linked_list_add_head( + struct linked_list * list, + LINKED_LIST_DATA_TYPE data ); + struct linked_list * linked_list_add_tail( + struct linked_list * list, + LINKED_LIST_DATA_TYPE data ); + LINKED_LIST_DATA_TYPE linked_list_pop_head(struct linked_list * list); + LINKED_LIST_DATA_TYPE linked_list_pop_tail(struct linked_list * list); + LINKED_LIST_DATA_TYPE linked_list_read( + struct linked_list * list, + uint8_t position ); + struct linked_list * linked_list_copy(struct linked_list * list); + void linked_list_free(struct linked_list * list); + + + // typedefs, for user code + typedef struct linked_list * linked_list_t; + typedef struct linked_list_node * linked_list_node_t; + + // aliases, for user code + #define list_t linked_list_t + #define list_new linked_list_new + #define list_push linked_list_add_head + #define list_append linked_list_add_tail + #define list_pop linked_list_pop_head + #define list_pop_tail linked_list_pop_tail + #define list_read linked_list_read + #define list_copy linked_list_copy + #define list_free linked_list_free + + #define queue_t list_t + #define queue_new list_new + #define queue_append list_append + #define queue_pop list_pop + #define queue_read list_read + #define queue_copy list_copy + #define queue_free list_free + + #define stack_t list_t + #define stack_new list_new + #define stack_push list_push + #define stack_pop list_pop + #define stack_read list_read + #define stack_copy list_copy + #define stack_free list_free + + +#endif +