Singly Linked Lists¶
To use the singly linked list implementation, create an instance of the single_list
type using sl_create()
. You can then use the data management functions to add and remove elements from the list. You can also use the functional data operations to transform, reduce, or filter the data in the list.
/* single_list.h - Reverse and take the absolute value of a list of numbers
* using a doubly linked list as a stack.
* Copyright (C) 2018 Quytelda Kahja
*
* This file is part of focs.
*
* focs is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* focs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with focs. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <list/single_list.h>
#include <focs/generics/hof.h>
static const struct ds_properties props = {
.data_size = sizeof(int),
};
static int my_abs(int n)
{
if(n < 0)
n = (-n);
return n;
}
WRAP_MAPPABLE(my_abs, int, my_abs_mappable);
int main(int argc, char * argv[])
{
int * inputs;
int ** outputs;
single_list my_list;
inputs = calloc(argc, sizeof(int));
outputs = calloc(argc, sizeof(int *));
if(!inputs || !outputs)
return -1; // out of memory
my_list = sl_create(&props);
/* Push the numbers onto the stack. */
for(int i = 1; i < argc; i++) {
inputs[i] = atoi(argv[i]);
sl_push_head(my_list, &inputs[i]);
}
/* Transform the list by mapping my_abs over the list. */
map(my_list, my_abs_mappable);
/* Output each number popped from the stack. */
for(int i = 1; i < argc; i++) {
outputs[i] = sl_pop_head(my_list);
printf("%d ", *outputs[i]);
}
putchar('\n');
free(inputs);
free(outputs);
sl_destroy(&my_list);
return 0;
}
Creation and Destruction¶
-
single_list
sl_create
(const struct ds_properties *props)¶ Allocate and initialize a new singly linked list.
Allocates a new singly linked list at the structure pointer pointed to by
list
.- Parameters
props
: The data structure properties
- Return
- Upon successful completion, sl_alloc() shall return
0
. Otherwise,-1
shall be returned anderrno
set to indicate the error.
-
void
sl_destroy
(single_list *list)¶ Destroy and deallocate a singly linked list.
De-allocates the singly linked list at the structure pointer pointed to by
list
, as well as de-allocating all data elements contained withinlist
.- Parameters
list
: A pointer to asingle_list
instance.
Data Management¶
-
bool
sl_empty
(const single_list list)¶ Determine if a list is empty.
- Return
true
iflist
is empty,false
otherwise.- Parameters
list
: The list to check
-
void
sl_push_head
(single_list list, const void *data)¶ Push a new data element to the head of the list.
Push a newly allocated copy of
data
onto the head oflist
.- Parameters
list
: The list to push ontodata
: A pointer to the data to push
-
void
sl_push_tail
(single_list list, const void *data)¶ Push a new data element to the tail of the list.
Push a newly allocated copy of
data
onto the tail oflist
.- Parameters
list
: The list to push ontodata
: A pointer to the data to push
-
void *
sl_pop_head
(single_list list)¶ Pop a data element from the head of a list.
Remove and return the data element at the head of
list
. After this operation the returned data element will no longer be stored inlist
.- Parameters
list
: The list to pop from
- Return
- A pointer to the data element at the head of
list
. This pointer must be explicitly freed with free() when it is no longer needed. It is not equivalent to the pointer which was used to insert the data intolist
.
-
void *
sl_pop_tail
(single_list list)¶ Pop a data element from the tail of a list.
Remove and return the data element at the tail of
list
. After this operation the returned data element will no longer be stored inlist
.- Parameters
list
: The list to pop from
- Return
- A pointer to the data element at the tail of
list
. This pointer must be explicitly freed with free() when it is no longer needed. It is not equivalent to the pointer which was used to insert the data intolist
.
-
bool
sl_elem
(const single_list list, const void *data)¶ Determine if a list contains a value.
Determines if
list
contains an entry matchingdata
. The operation compares the contents of the memory pointed to bydata
, and not the memory addresses of the data pointers.- Parameters
list
: The list to searchdata
: The data to search for in the list
- Return
true
if a matching entry is found, otherwisefalse
-
bool
sl_insert
(single_list list, const void *data, const size_t pos)¶ Insert a new data element to a given position in a list.
Insert a newly allocated copy of
data
intolist
at the index indicated bypos
.- Parameters
list
: The list to inesrt intodata
: A pointer to the data to insertpos
: The position to insert the element at (must be an index in the range0..list->length
)
- Return
true
if the insertion succeeds, otherwisefalse
.
-
bool
sl_delete
(single_list list, const size_t pos)¶ Delete a data element from a given position in a list.
Delete the copy of
data
stored inlist
at the index indicated bypos
.- Parameters
list
: The list to delete frompos
: The position to delete the element at (must be an index in the range0..list->length - 1
)
- Return
true
if the deletion succeeds, otherwisefalse
.
-
void *
sl_remove
(single_list list, const size_t pos)¶ Delete and return a data element from a given position in a list.
Delete the reference to
data
stored inlist
at the index indicated bypos
.- Parameters
list
: The list to delete frompos
: The position to delete the element at (must be an index in the range0..list->length - 1
)
- Return
- A pointer to the data removed from
list
, orNULL
on failure. This pointer must be explicitly freed with free() when it is no longer needed. It is not equivalent to the pointer which was used to insert the data intolist
.
-
void *
sl_fetch
(single_list list, const size_t pos)¶ Fetch a data element from a given position in a list.
Fetch the data stored at index
pos
inlist
.- Parameters
list
: The list to fetch frompos
: The index to fetch the element from (must be an index in the range0..list->length - 1
)
- Return
- A pointer to the data at index
pos
, orNULL
on failure. This pointer should not be free()d explicitly, or the list will become corrupted. This pointer will be free()d when sl_destroy() is called, so if the data is needed after the list is destroyed, make a copy of it, or make sure to call sl_remove() on the data’s index before destroying the list.
Higher Order Functions¶
-
void
sl_map
(single_list list, const map_fn fn)¶ Map a function over a linked list in-place.
A map operation iterates over
list
and transforms each data element using the functionfn
, replacing the old value with the result of the transformation. In pseudo-code:for i from 0 to list->length: list[i] = fn(list[i])
- Parameters
list
: A list of valuesfn
: A function that will transform each value in the list
-
void *
sl_foldr
(const single_list list, const foldr_fn fn, const void *init)¶ Right associative fold for singly linked lists.
A right associative fold uses the binary function
fn
to sequentially reduce a list of values to a single value, starting from some initial valueinit
:fn(init, fn(list[0], fn(list[1], ...)))
- Parameters
list
: A list of values to reducefn
: A binary function that will sequentially reduce valuesinit
: An initial value for the fold
- Return
- The result of a right associate fold over
list
. Iflist
is empty, the fold will be equal to the value ofinit
.
-
void *
sl_foldl
(const single_list list, const foldl_fn fn, const void *init)¶ Left associative fold for singly linked lists.
A left associative fold uses the binary function
fn
to sequentially reduce a list of values to a single value, starting from some initial valueinit
:fn(fn(fn(..., init), list[0]), list[1])
- Parameters
list
: A list of values to reducefn
: A binary function that will sequentially reduce valuesinit
: An initial value for the fold
- Return
- The result of a left associate fold over
list
. Iflist
is empty, the fold will be equal to the value ofinit
.
-
bool
sl_any
(single_list list, const pred_fn pred)¶ Determine if any value in a list satisifies some condition.
Iterate over each value stored in
list
, and determine if any of them satisfiespred
.- Parameters
list
: A list of valuespred
: The predicate function
- Return
- This function shall return
true
if the predicatepred
is satisfied by any data element inlist
; otherwisefalse
shall be returned.
-
bool
sl_all
(single_list list, const pred_fn pred)¶ Determines if all values in a list satisify some condition.
Iterate over each value stored in
list
, and determine if all of them satisfypred
.- Parameters
list
: A list of valuespred
: The predicate function (representing a condition to be satisfied).
- Return
- This function shall return
true
if the predicatepred
is satisfied by all data elements inlist
; otherwisefalse
shall be returned.
-
bool
sl_filter
(single_list list, const pred_fn pred)¶ Filter a list to contain only values that satisfy some predicate.
Filter
list
in-place by removing elements that do not satisfy the predicatepred
. Elements that do satisfy the predicatepred
are not removed from the list.- Parameters
list
: The list to filterpred
: The predicate
-
bool
sl_drop_while
(single_list list, const pred_fn pred)¶ Drop elements from the head of the list until the predicate is unsatisfied.
Drop each element that satisfies the predicate
pred
, starting at the beginning oflist
and continuing until reaching the first element that does not satisfy the predicatepred
.- Parameters
list
: The list to drop frompred
: The predicate
This function is an in-place equivalent of Haskell’s dropWhile.
-
bool
sl_take_while
(single_list list, const pred_fn pred)¶ Keep elements from the head of the list until the predicate is unsatisfied.
Iterate over each element of
list
, starting at the beginning, that satisfies the predicatepred
. Once an element that does not satisfy the predicatepred
is reached, drop the rest of the list, including that element.- Parameters
list
: The list to take frompred
: The predicate
This function is an in-place equivalent of Haskell’s takeWhile.