More tests and documentation and utilities.
This commit is contained in:
parent
29d32a612f
commit
9cf9159e4b
|
@ -0,0 +1,47 @@
|
|||
.DA
|
||||
|
||||
.TL
|
||||
single_linked_list.h
|
||||
|
||||
.AU
|
||||
Wael Karram
|
||||
|
||||
.AB no
|
||||
Documentation for single_linked_list.h
|
||||
.AE
|
||||
|
||||
.ND
|
||||
|
||||
.PP
|
||||
This header defines a linked list, with one link per node. Using the prepoccessor variable SINGLE_LINKED_LIST_H used as an include guard.
|
||||
.br
|
||||
Relies on single_node.h to implement the nodes.
|
||||
|
||||
.PP
|
||||
These are the compile-time constants declared by this header:
|
||||
.br
|
||||
SUCCESS_CODE_SINGLE_LINKED_LIST_C, this is the code returned by a function on succcess, evaluates to 1.
|
||||
.br
|
||||
FAILURE_CODE_SINGLE_LINKED_LIST_C, this is the code returned by a function on failure, evaluates to 0.
|
||||
.br
|
||||
INDEX_NOT_FOUND_CODE_SINGLE_LINKED_LIST_C, this is the code returned by a function when a requested index is not found, evaluates to -1.
|
||||
.br
|
||||
INVALID_INPUT_CODE_SINGLE_LINKED_LIST_C, this is the code returned by a function when recieving invalid input, evaluates to -2.
|
||||
.br
|
||||
CODE_FREE_SUCCESS_MALFORMED_SINGLE_LINKED_LIST_C, this code is returned when freeing the data is successful, but the list is maformed, evaluates to -1.
|
||||
.br
|
||||
INDEX_HEAD_LINKED_LIST, this is the index of the head of the linked list, evaluates to 0.
|
||||
|
||||
|
||||
.PP
|
||||
These are the function defitions and input arguments for this data structre.
|
||||
.br
|
||||
Defines a single struct
|
||||
.UL node_t \0which
|
||||
has the fields
|
||||
.I "next" \0and
|
||||
.I "data" ,
|
||||
the former of which is another node pointer, and the latter is a void pointer.
|
||||
.br
|
||||
It is of note that this header type-defines the aformentioned node as
|
||||
.I "node_t" .
|
|
@ -34,9 +34,26 @@ INDEX_HEAD_LINKED_LIST, this is the index of the head of the linked list, evalua
|
|||
|
||||
|
||||
.PP
|
||||
These are the function defitions and input arguments for this data structre.
|
||||
These are the function defitions and input arguments for this data structre:
|
||||
.br
|
||||
Defines a single struct
|
||||
linked_list* initialize_single_linked_list(): initializes an empty linked list, returns NULL on failure.
|
||||
.br
|
||||
int append_node_single_linked_list(linked_list_t *list, node_t *node): appends the node to the given list, returns success if worked, otherwise failure code is returned.
|
||||
.br
|
||||
int prepend_node_single_linked_list(linked_list_t *list, node_t *node): prepends the node to the given list, returns success if worked, otherwise failure code is returned.
|
||||
.br
|
||||
int append_node_data_single_linked_list(linked_list_t *list, void *data): much like the node appending function, but creates the node itself - note that the data can be NULL, will also return failure code when allocation of the node fails.
|
||||
.br
|
||||
int prepend_node_data_single_linked_list(linked_list_t *list, void *data): much like the node prepending function, but creates the node itself - note that the data can be NULL, will also return failure code when allocation of the node fails.
|
||||
.br
|
||||
int add_node_i_single_linked_list(linked_list_t *list, node_t *node, int i): much like append node, but might also fail when the index is invalid (returning the aforementioned error code).
|
||||
.br
|
||||
int add_node_data_i_single_linked_list(linked_list_t *list, void *data, int i): much like the node insertion function, but also attempts to allocate a node and put the data in it beforehand, will fail with the failure error code if allocation fails.
|
||||
.br
|
||||
void* read_node_i_songle_linked_list(linked_list_t *list, int i): attempts to return the stored data at the ith node, will return NULL if the list is NULL or index is invalid.
|
||||
.br
|
||||
|
||||
|
||||
.UL node_t \0which
|
||||
has the fields
|
||||
.I "next" \0and
|
||||
|
|
|
@ -40,9 +40,11 @@ node_t* pop(stack_t *stack) {
|
|||
/* This function "peeks" at the top of the stack, will return NULL on error (in input/internal). */
|
||||
const void* peek(stack_t *stack) {
|
||||
/* Sanity check. */
|
||||
if (stack == NULL)
|
||||
if (stack == NULL || stack->head == NULL)
|
||||
return NULL;
|
||||
|
||||
|
||||
/* Return the data in the head. */
|
||||
return stack->head->data;
|
||||
}
|
||||
|
||||
/* This function pushes a node in, returns PUSH_SUCCESS on succes and PUSH_FAIL on failure. */
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#define STRZCPY_C
|
||||
/* Include statements. */
|
||||
#include "strzcpy.h"
|
||||
#endif //STRZCPY_C
|
||||
|
||||
/**
|
||||
* This function takes a destination buffer, a source buffer and a length.
|
||||
|
@ -17,5 +18,3 @@ char *strzcpy(char *restrict dst, const char* restrict src, size_t len) {
|
|||
dst[len - 1] = '\0';
|
||||
return end;
|
||||
}
|
||||
|
||||
#endif //STRZCPY_C
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
/* Include statements. */
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "../linked_lists/double_linked_list.c"
|
||||
|
||||
/* Define constants. */
|
||||
#define PRINT_INFO_TESTING_START "Starting tests.\n"
|
||||
#define PRINT_INFO_TESTING_END "Done testing.\n"
|
||||
#define ERROR_TEXT_RANDOM_LIST_FAIL_ALLOCATION "Long list test failed because of allocation errors!\n"
|
||||
#define SOME_TEST_FAILED "Recheck the tests, one of them failed!\n"
|
||||
#define FUNCTION_ERROR "Some function encountered a data error in testing.\n"
|
||||
#define INITIAL_LIST_LENGTH 0
|
||||
#define LIST_LENGTH_ONE 1
|
||||
#define LIST_LENGTH_LONG_TEST 4096
|
||||
|
||||
/* Define functions. */
|
||||
double_node_t* generate_random_node();
|
||||
double_linked_list_t* generate_long_random_list(int length);
|
||||
int list_count_length(double_linked_list_t *list);
|
||||
int test_linked_lists();
|
||||
|
||||
/* Starting point. */
|
||||
int main() {
|
||||
printf(PRINT_INFO_TESTING_START);
|
||||
if (test_linked_lists()) {
|
||||
printf(SOME_TEST_FAILED);
|
||||
}
|
||||
printf(PRINT_INFO_TESTING_END);
|
||||
}
|
||||
|
||||
/* This function generates a random number and puts it in a newly allocated node. */
|
||||
/* Caller has to free memory afterwards, returns NULL on failure. */
|
||||
double_node_t* generate_random_node() {
|
||||
/* The node to return. */
|
||||
double_node_t* result;
|
||||
int *value;
|
||||
|
||||
/* Attempt to allocate the node. */
|
||||
result = (double_node_t*) malloc(sizeof(double_node_t));
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
value = (int*) malloc(sizeof(int));
|
||||
if (value == NULL) {
|
||||
free(result);
|
||||
return NULL;
|
||||
}
|
||||
*value = random();
|
||||
|
||||
/* Store and return. */
|
||||
result->next = NULL;
|
||||
result->previous = NULL;
|
||||
result->data = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* This function generates a long list with random values in the nodes, returns NULL on failures. */
|
||||
/* Length denotes the length of the list. */
|
||||
double_linked_list_t* generate_long_random_list(int length) {
|
||||
/* Sanity check. */
|
||||
if (length <= 0)
|
||||
return NULL;
|
||||
/* Variables. */
|
||||
double_linked_list_t *list;
|
||||
double_node_t *current;
|
||||
int i;
|
||||
|
||||
/* Allocate the list. */
|
||||
list = initialize_double_linked_list();
|
||||
if (list == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Fill the list with random nodes. */
|
||||
/* First node. */
|
||||
current = generate_random_node();
|
||||
if (current == NULL) {
|
||||
free(list);
|
||||
return NULL;
|
||||
}
|
||||
/* Attempt to append. */
|
||||
if (!append_node_double_linked_list(list, current)) {
|
||||
free(current->data);
|
||||
free(current);
|
||||
free(list);
|
||||
return NULL;
|
||||
}
|
||||
/* Loop and add the rest. */
|
||||
for (i = 1; i < length; i++) {
|
||||
/* Generate and attempt to append. */
|
||||
current = generate_random_node();
|
||||
if (!append_node_double_linked_list(list, current)) {
|
||||
/* Abort. */
|
||||
free(current->data);
|
||||
free(current);
|
||||
clear_list_data_double_linked_list(&list, NULL);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the list's length. */
|
||||
list->length = length;
|
||||
/* Return the result. */
|
||||
return list;
|
||||
}
|
||||
|
||||
/* This function checks the actual length of a list. */
|
||||
int list_count_length(double_linked_list_t *list) {
|
||||
if (list == NULL || list->head == NULL)
|
||||
return 0;
|
||||
/* Loop and count. */
|
||||
double_node_t *current = list->head;
|
||||
int count = 0;
|
||||
while (current != NULL) {
|
||||
count++;
|
||||
current = current->next;
|
||||
}
|
||||
/* Return the result. */
|
||||
return count;
|
||||
}
|
||||
|
||||
/* This function does the testing. */
|
||||
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();
|
||||
/* Check that it was correctly created. */
|
||||
assert(list != NULL);
|
||||
assert(list->length == INITIAL_LIST_LENGTH);
|
||||
assert(list->head == NULL);
|
||||
assert(list->tail == NULL);
|
||||
|
||||
/* Generate and store the node. */
|
||||
node = generate_random_node();
|
||||
|
||||
/* Attempt to add it to the list. */
|
||||
append_node_double_linked_list(list, node);
|
||||
/* Check that the list grew and that both the head and tail got set. */
|
||||
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_index_pointer_double_linked_list(list, node) == 0);
|
||||
|
||||
/* Attempt to free the nodes and then the list. */
|
||||
remove_node_i_data_double_linked_list(list, 0, NULL);
|
||||
assert(list->length == INITIAL_LIST_LENGTH);
|
||||
assert(list->head == NULL);
|
||||
node = NULL;
|
||||
free(list);
|
||||
list = NULL;
|
||||
|
||||
/* Attempt to allocate a long list. */
|
||||
list = generate_long_random_list(LIST_LENGTH_LONG_TEST);
|
||||
if (list == NULL) {
|
||||
printf(ERROR_TEXT_RANDOM_LIST_FAIL_ALLOCATION);
|
||||
return 1;
|
||||
}
|
||||
assert(list->length == LIST_LENGTH_LONG_TEST);
|
||||
assert(list->length == list_count_length(list));
|
||||
/* Test the get head/tail functions. */
|
||||
assert(get_node_head_double_linked_list(list) == list->head);
|
||||
tail = get_node_tail_double_linked_list(list);
|
||||
assert(tail != NULL && tail->next == NULL);
|
||||
/* Test the indexer functions. */
|
||||
assert(get_node_index_pointer_double_linked_list(list, tail) == (list->length - 1));
|
||||
/* Test the freeing functions. */
|
||||
clear_list_data_double_linked_list(&list, NULL);
|
||||
assert(list == NULL);
|
||||
|
||||
/* Ran successfully, return 0. */
|
||||
return 0;
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
/* Define functions. */
|
||||
tree_node_t* generate_random_tree_node();
|
||||
int comparison_function_int(int *first, int *second);
|
||||
int comparison_function_int(const void *first, const void *second);
|
||||
tree_node_t* insert_sorted_array_into_tree(int *array, int start, int end);
|
||||
tree_node_t* build_tree(int **arr);
|
||||
int check_tree_bst(tree_node_t *root, int (*comparison_function)());
|
||||
|
@ -59,8 +59,8 @@ tree_node_t* generate_random_tree_node() {
|
|||
}
|
||||
|
||||
/* This function is used to compare two integers (given their pointers), exhibits undefined behaviour on NULL pointers. */
|
||||
int comparison_function_int(int *first, int *second) {
|
||||
return *first == *second ? TREE_COMPARISON_EQUAL_TO : ((*first < *second) ? TREE_COMPARISON_SMALLER_THAN : TREE_COMPARISON_LARGER_THAN);
|
||||
int comparison_function_int(const void *first, const void *second) {
|
||||
return *((int*)first) == *((int*)second) ? TREE_COMPARISON_EQUAL_TO : ((*((int*)first) < *((int*)second)) ? TREE_COMPARISON_SMALLER_THAN : TREE_COMPARISON_LARGER_THAN);
|
||||
}
|
||||
|
||||
/* This function will generate a balanced tree from the given sorted array, returns the root. */
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
/* This header defines a struct for storing function timing information. */
|
||||
#ifndef TIME_FUNCTION_H
|
||||
#define TIME_FUNCTION_H
|
||||
|
||||
/* Struct used to store the results. */
|
||||
typedef struct function_run_time {
|
||||
/* Function name. */
|
||||
char *name;
|
||||
/* Length of run time. */
|
||||
double time;
|
||||
} function_run_time;
|
||||
#endif /* TIME_FUNCTION_H */
|
Loading…
Reference in New Issue