#include "sorted-int-list.h" /******************************************************************************* * * definitions (implementation) of functions declared in .h file * * descriptions of functions in .h file * * implementation uses recursion * * functions that can change list have associated "helper" functions that * (mostly) return updated list */ #include #include #include /* * declarations of helper functions * ("static" makes them accessible only within this file) */ /* return list with node inserted */ static sorted_int_list_node_t * helper_insert(sorted_int_list_node_t * lst, sorted_int_list_node_t * newnode); /* return list with node(s) remove */ static sorted_int_list_node_t * helper_remove(sorted_int_list_node_t * lst, int n); /* free all nodes */ static void helper_remove_all(sorted_int_list_node_t * lst); /******************************************************************************* * * definitions of functions in .h file */ /* * insert: * * create new node (and no, a local variable won't do!) * * call helper function to insert; helper returns updated list */ bool sorted_int_list_insert(sorted_int_list_node_t ** lst_p, int n) { sorted_int_list_node_t *new_p = malloc(sizeof(*new_p)); if (new_p == NULL) { return false; } new_p->data = n; new_p->next = NULL; *lst_p = helper_insert(*lst_p, new_p); return true; } /* * count: * * recursive strategy: * * if list is empty, count is 0 * * else if head of list is smaller than item, count is 0 * * else if head of list matches, count is 1 plus count in rest of list * * else count is count in rest of list */ int sorted_int_list_count(sorted_int_list_node_t * lst, int n) { if (lst == NULL) { return 0; } else if (lst->data < n) { return 0; } else { int rest = sorted_int_list_count(lst->next, n); if (lst->data == n) { return 1 + rest; } else { return rest; } } } /* * remove: * * call helper function to remove; helper returns updated list */ void sorted_int_list_remove(sorted_int_list_node_t ** lst_p, int n) { *lst_p = helper_remove(*lst_p, n); } /* * "remove" all nodes (free space): * * call helper function to remove; set caller's pointer to NULL to mean * empty list */ void sorted_int_list_remove_all(sorted_int_list_node_t ** lst_p) { helper_remove_all(*lst_p); *lst_p = NULL; } /* * print: * * recursive strategy: * * if empty list, nothing to do * * else print first item and then rest of list */ void sorted_int_list_print(sorted_int_list_node_t * lst, FILE * f, char * fmt) { if (lst != NULL) { fprintf(f, fmt, lst->data); sorted_int_list_print(lst->next, f, fmt); } } /* * filter * * recursive strategy: * * if empty list, return empty list * * if first item matches, return copy of it plus result of filter on rest * * else return result of filter on rest */ sorted_int_list_node_t * sorted_int_list_filter(sorted_int_list_node_t * lst, bool (*filter_fcn)(int), bool * error) { *error = false; /* default value */ if (lst == NULL) { return NULL; } else if (filter_fcn(lst->data)) { sorted_int_list_node_t *new_p = malloc(sizeof(*new_p)); if (new_p == NULL) { *error = true; } else { new_p->data = lst->data; new_p->next = sorted_int_list_filter(lst->next, filter_fcn, error); } return new_p; } else { return sorted_int_list_filter(lst->next, filter_fcn, error); } } /* * map * * recursive strategy: * * if empty list, return empty list * * else return result of map on first followed by result of map on rest */ sorted_int_list_node_t * sorted_int_list_map(sorted_int_list_node_t * lst, int (*map_fcn)(int), bool * error) { *error = false; /* default value */ if (lst == NULL) { return NULL; } else { sorted_int_list_node_t *new_p = malloc(sizeof(*new_p)); if (new_p == NULL) { *error = true; } else { new_p->data = map_fcn(lst->data); new_p->next = sorted_int_list_map(lst->next, map_fcn, error); } return new_p; } } /* * definitions of helper functions */ /* * helper for insert -- returns list with item inserted * * recursive strategy: * * if empty list, new list is just the item * * else if item smaller than head of list, new list is item followed by * list * * else new list is head of list, then result of inserting item into * rest of list */ static sorted_int_list_node_t * helper_insert(sorted_int_list_node_t * lst, sorted_int_list_node_t * newnode) { if (lst == NULL) { return newnode; } else if (newnode->data < lst->data) { newnode->next = lst; return newnode; } else { lst->next = helper_insert(lst->next, newnode); return lst; } } /* * helper for remove -- returns list with item(s) removed * * recursive strategy: * * if empty list, new list is list * * else if item smaller than head of list, not in list, so new list is just * list * * else if item matches head of list, new list is rest of list, with any * other occurrences of item removed * * else new list is list's head followed by result of removing item from * rest of list */ static sorted_int_list_node_t * helper_remove(sorted_int_list_node_t * lst, int n) { if (lst == NULL) { /* empty list */ return lst; } else if (lst->data > n) { /* element not in list at all */ return lst; } else if (lst->data == n) { /* element in list -- remove this one and recurse */ sorted_int_list_node_t *new_list = helper_remove(lst->next, n); free(lst); return new_list; } else { /* element could be in list, but later -- recurse */ sorted_int_list_node_t *new_list = helper_remove(lst->next, n); lst->next = new_list; return lst; } } /* * helper for "remove all" -- just frees all nodes * * recursive strategy: * * if empty list, nothing to do * * else free tail of list, then its head (and no, we can't do it the * other way around!) */ void helper_remove_all(sorted_int_list_node_t * lst) { if (lst != NULL) { helper_remove_all(lst->next); free(lst); } }