More streamlining of double linked lists.
This commit is contained in:
parent
30ad230ade
commit
ac7e772a05
|
@ -21,8 +21,10 @@
|
|||
#define DOUBLE_LINKED_LIST_H
|
||||
#include "../nodes/double_node.h"
|
||||
/* Include assert.h to allow code generation, but only run with debug flag. */
|
||||
#ifndef DEBUG
|
||||
#ifdef DEBUG
|
||||
#ifndef NDEBUG
|
||||
#define NDEBUG
|
||||
#endif /* NDEBUG. */
|
||||
#endif /* DEBUG. */
|
||||
#include <assert.h>
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
/* This function initializes a new empty queue. */
|
||||
/* Will return a pointer to the queue on success, otherwise will return NULL. */
|
||||
queue_t *initialize_queue() {
|
||||
static inline queue_t *initialize_queue() {
|
||||
/* Variables. */
|
||||
queue_t *result;
|
||||
|
||||
|
@ -59,50 +59,26 @@ queue_t *initialize_queue() {
|
|||
}
|
||||
|
||||
/* This function enqueues a node. */
|
||||
/* This function attempts to enqueue a given node into the given queue, on success will return SUCCESS_CODE_QUEUE_C, otherwise will return FAILURE_CODE_QUEUE_C. */
|
||||
/* Note that if either the queue or node pointer are NULL, the function will automatically fail. */
|
||||
int enqueue(queue_t *queue, node_t *node) {
|
||||
/* Local variables. */
|
||||
int result;
|
||||
|
||||
/* This function attempts to enqueue a given node into the given queue. */
|
||||
static inline void enqueue(queue_t *queue, node_t *node) {
|
||||
/* Input sanity check. */
|
||||
if (!queue || !(queue->list) || !node || ((!(queue->list->head) && queue->tail) || (queue->list->head && !(queue->tail))))
|
||||
return FAILURE_CODE_QUEUE_C;
|
||||
assert(queue && (queue->list) && node && (((queue->list->head) && (queue->tail)) || (!(queue->list->head) && !(queue->tail))));
|
||||
|
||||
/* Delegate. */
|
||||
result = prepend_node_single_linked_list(queue->list, node);
|
||||
prepend_node_single_linked_list(queue->list, node);
|
||||
/* Check if to update the tail. */
|
||||
if ((!(queue->tail) || queue->list->length == 1) && result);
|
||||
if (!(queue->tail) || queue->list->length == 1)
|
||||
queue->tail = node;
|
||||
/* Return the result. */
|
||||
return result;
|
||||
|
||||
/* Attempt to enqueue the node. */
|
||||
/* Check if the queue is empty. */
|
||||
/*if (!(queue->list->head)) {
|
||||
node->next = NULL;
|
||||
queue->tail = node;
|
||||
} else
|
||||
node->next = queue->list->head;
|
||||
/* Relink the head. */
|
||||
/*queue->list->head = node;
|
||||
/* Increase the length. */
|
||||
/*(queue->list->length)++;
|
||||
|
||||
/* Success. */
|
||||
/*return SUCCESS_CODE_QUEUE_C;*/
|
||||
}
|
||||
|
||||
/* This function allocates and enqueues a node. */
|
||||
/* This function attempts to create a node then enqueue it into the given queue, on success will return SUCCESS_CODE_QUEUE_C, otherwise will return FAILURE_CODE_QUEUE_C. */
|
||||
/* Note that if either the queue pointer is NULL or node allocation fails, the function will automatically fail. */
|
||||
int enqueue_data(queue_t *queue, void *data) {
|
||||
static inline int enqueue_data(queue_t *queue, void *data) {
|
||||
/* Variables. */
|
||||
node_t *node;
|
||||
|
||||
/* Input sanity check. */
|
||||
if (!queue || !(queue->list) || ((!(queue->list->head) && queue->tail) || (queue->list->head && !(queue->tail))))
|
||||
return FAILURE_CODE_QUEUE_C;
|
||||
assert(queue && (queue->list) && (((queue->list->head) && (queue->tail)) || (!(queue->list->head) && !(queue->tail))));
|
||||
|
||||
/* Attempt to allocate the node. */
|
||||
node = (node_t*) malloc(sizeof(node));
|
||||
|
@ -113,36 +89,25 @@ int enqueue_data(queue_t *queue, void *data) {
|
|||
node->data = data;
|
||||
|
||||
/* Attempt to enqueue the node. */
|
||||
return enqueue(queue, node);
|
||||
/* Check if the queue is empty. */
|
||||
/*if (!(queue->list->head)) {
|
||||
node->next = NULL;
|
||||
queue->tail = node;
|
||||
} else
|
||||
node->next = queue->list->head;
|
||||
/* Relink the head. */
|
||||
/*queue->list->head = node;
|
||||
/* Increase the length. */
|
||||
/*(queue->list->length)++;
|
||||
|
||||
/* Success. */
|
||||
/*return SUCCESS_CODE_QUEUE_C;*/
|
||||
enqueue(queue, node);
|
||||
return SUCCESS_CODE_QUEUE_C;
|
||||
}
|
||||
|
||||
/* This function dequeues a node. */
|
||||
/* This function attempts to dequeue a node from the given queue, on success will return a pointer to the dequeued node - otherwise returns NULL. */
|
||||
/* Note that if either the queue or node pointer are NULL, the function will automatically fail. */
|
||||
node_t *dequeue(queue_t *queue) {
|
||||
static inline node_t *dequeue(queue_t *queue) {
|
||||
/* Variables. */
|
||||
node_t *result, *replacement, *tmp;
|
||||
int i;
|
||||
|
||||
/* Input sanity check. */
|
||||
if (!queue || !(queue->list) || ((!(queue->list->head) && queue->tail) || (queue->list->head && !(queue->tail))))
|
||||
return NULL;
|
||||
assert(queue && (queue->list) && (((queue->list->head) && (queue->tail)) || (!(queue->list->head) && !(queue->tail))));
|
||||
|
||||
/* Attempt to dequeue the node. */
|
||||
else if (queue->list->length == 1) {
|
||||
/* Check if the length is zero. */
|
||||
if (!(queue->list->length) || !(queue->tail))
|
||||
return NULL;
|
||||
if (queue->list->length == 1) {
|
||||
/* A queue that is of length 1. */
|
||||
result = queue->list->head;
|
||||
queue->list->head = NULL;
|
||||
|
@ -167,38 +132,60 @@ node_t *dequeue(queue_t *queue) {
|
|||
}
|
||||
|
||||
/* This function frees all the nodes of the given queue and the queue itself (setting it to NULL). */
|
||||
/* Note that it doesn't touch the data stored within the queue's nodes, returns 1 on success and 0 on failure - in the latter case might exhibit undefined behavior. */
|
||||
int clear_queue(queue_t **queue) {
|
||||
/* Note that it doesn't touch the data stored within the queue's nodes, might exhibit undefined behavior when the internal state of the queue isn't coherent. */
|
||||
static inline void clear_queue(queue_t **queue) {
|
||||
/* Sanity check. */
|
||||
if (!queue || !(*queue))
|
||||
return FAILURE_CODE_QUEUE_C;
|
||||
assert(queue && (*queue) && ((*queue)->list));
|
||||
|
||||
/* Delegate to implementation (linked list). */
|
||||
if (!clear_list_single_linked_list(&((*queue)->list)))
|
||||
return FAILURE_CODE_QUEUE_C;
|
||||
clear_list_single_linked_list(&((*queue)->list));
|
||||
|
||||
/* Successfully cleared the internal structure, just free the queue struct and set the pointer to NULL. */
|
||||
free(*queue);
|
||||
*queue = NULL;
|
||||
return SUCCESS_CODE_QUEUE_C;
|
||||
}
|
||||
|
||||
/* This function frees all the nodes of the given queue and the queue itself (setting it to NULL).*/
|
||||
/* Note that it does free the stored data, returns 1 on success and 0 on failure - in the latter case might exhibit undefined behavior. */
|
||||
/* Might exhibit undefined behavior on inconsistent internal state of the queue. */
|
||||
/* If free_function is NULL, then it the standard library's free() call is used. */
|
||||
int clear_queue_data(queue_t **queue, void (*free_func)()) {
|
||||
static inline void clear_queue_data(queue_t **queue, void (*free_func)(const void*)) {
|
||||
/* Sanity check. */
|
||||
if (!queue || !(*queue))
|
||||
return FAILURE_CODE_QUEUE_C;
|
||||
assert(queue && (*queue));
|
||||
|
||||
/* Delegate to implementation (linked list). */
|
||||
if (!clear_list_data_single_linked_list(&((*queue)->list), free_func))
|
||||
return FAILURE_CODE_QUEUE_C;
|
||||
clear_list_data_single_linked_list(&((*queue)->list), free_func);
|
||||
|
||||
/* Successfully cleared the internal structure, just free the queue struct and set the pointer to NULL. */
|
||||
free(*queue);
|
||||
*queue = NULL;
|
||||
return SUCCESS_CODE_QUEUE_C;
|
||||
}
|
||||
|
||||
/* This function deletes all the nodes of the given queue, but doesn't touch the queue struct itself or the stored data. */
|
||||
static inline void clear_queue_nodes(queue_t *queue) {
|
||||
/* Sanity check. */
|
||||
assert(queue && (queue->list));
|
||||
|
||||
/* Check if there is anything to remove. */
|
||||
if (!(queue->list->length) || !(queue->list->head))
|
||||
return;
|
||||
|
||||
/* Delegate to implementation in linked list. */
|
||||
clear_list_nodes_single_linked_list(queue->list);
|
||||
queue->tail = NULL;
|
||||
}
|
||||
|
||||
/* This function deletes all the nodes of the given queue, but doesn't touch the queue struct itself or the stored data. */
|
||||
static inline void clear_queue_nodes_data(queue_t *queue, void (*free_function)(const void*)) {
|
||||
/* Sanity check. */
|
||||
assert(queue && (queue->list));
|
||||
|
||||
/* Check if there is anything to remove. */
|
||||
if (!(queue->list->length) || !(queue->list->head))
|
||||
return;
|
||||
|
||||
/* Delegate to implementation in linked list. */
|
||||
clear_list_nodes_data_single_linked_list(queue->list, free_function);
|
||||
queue->tail = NULL;
|
||||
}
|
||||
|
||||
/* This function serializes the queue. */
|
||||
|
|
|
@ -43,18 +43,22 @@ typedef struct queue {
|
|||
} queue_t;
|
||||
|
||||
/* This function initializes a new queue. */
|
||||
queue_t *initialize_queue();
|
||||
static inline queue_t *initialize_queue();
|
||||
/* This function enqueues a node. */
|
||||
int enqueue(queue_t *queue, node_t *node);
|
||||
static inline void enqueue(queue_t *queue, node_t *node);
|
||||
/* This function creates and enqueues a node. */
|
||||
int enqueue_data(queue_t *queue, void *data);
|
||||
static inline int enqueue_data(queue_t *queue, void *data);
|
||||
/* This function dequeues the last node. */
|
||||
node_t *dequeue(queue_t *queue);
|
||||
/* This function deletes all the nodes of the given queue. */
|
||||
int clear_queue(queue_t **queue);
|
||||
/* This function deletes all the nodes of the given queue. */
|
||||
int clear_queue_data(queue_t **queue, void (*free_function)());
|
||||
static inline node_t *dequeue(queue_t *queue);
|
||||
/* This function deletes all the nodes of the given queue, including the queue itself. */
|
||||
static inline void clear_queue(queue_t **queue);
|
||||
/* This function deletes all the nodes of the given queue, including the stored data and the queue itself. */
|
||||
static inline void clear_queue_data(queue_t **queue, void (*free_function)(const void*));
|
||||
/* This function deletes all the nodes of the given queue, but doesn't touch the queue struct itself. */
|
||||
static inline void clear_queue_nodes(queue_t *queue);
|
||||
/* This function deletes all the nodes of the given queue - including the stored data - but doesn't touch the queue struct itself. */
|
||||
static inline void clear_queue_nodes_data(queue_t *queue, void (*free_function)(const void*));
|
||||
/* This function serializes the queue into an array, it relies on an array setting function and an allocated buffer. */
|
||||
void *serialize_queue(queue_t *queue, void (*array_setting_function)(void*, size_t, void*), void *array);
|
||||
static inline void *serialize_queue(queue_t *queue, void (*array_setting_function)(void*, size_t, void*), void *array);
|
||||
|
||||
#endif /* QUEUE_H */
|
||||
|
|
|
@ -195,7 +195,6 @@ int test_linked_lists() {
|
|||
/* Local variables. */
|
||||
double_linked_list_t *list;
|
||||
double_node_t *node, *tail;
|
||||
int error;
|
||||
|
||||
/* Initialize an empty list. */
|
||||
list = initialize_double_linked_list();
|
||||
|
@ -214,9 +213,7 @@ int test_linked_lists() {
|
|||
assert(list->length == LIST_LENGTH_ONE);
|
||||
assert(list->head != NULL && list->head == node);
|
||||
assert(list->tail != NULL && list->tail == node);
|
||||
assert(get_node_i_double_linked_list(list, 0, &error) == node);
|
||||
if (!error)
|
||||
printf(FUNCTION_ERROR);
|
||||
assert(get_node_i_double_linked_list(list, 0) == node);
|
||||
assert(get_node_index_pointer_double_linked_list(list, node) == 0);
|
||||
|
||||
/* Attempt to free the nodes and then the list. */
|
||||
|
|
|
@ -78,24 +78,20 @@ queue_t* generate_long_random_queue(int length) {
|
|||
return NULL;
|
||||
}
|
||||
/* Attempt to enqueue. */
|
||||
if (!enqueue(queue, current)) {
|
||||
free(current->data);
|
||||
free(current);
|
||||
free(queue);
|
||||
return NULL;
|
||||
}
|
||||
enqueue(queue, current);
|
||||
|
||||
/* Loop and enqueue the rest. */
|
||||
for (i = 1; i < length; i++) {
|
||||
/* Generate and attempt to enqueue. */
|
||||
current = generate_random_node();
|
||||
if (current == NULL || !enqueue(queue, current)) {
|
||||
if (current == NULL) {
|
||||
/* Abort. */
|
||||
free(current->data);
|
||||
free(current);
|
||||
clear_queue_data(&queue, NULL);
|
||||
return NULL;
|
||||
}
|
||||
enqueue(queue, current);
|
||||
}
|
||||
|
||||
/* Return the result. */
|
||||
|
|
Loading…
Reference in New Issue