write list docs, cleanup bintree and input docs

This commit is contained in:
Evan Burkey 2022-04-11 14:33:57 -07:00
parent d9d49f58bc
commit eb0fea1212
4 changed files with 231 additions and 9 deletions

2
.gitignore vendored
View File

@ -2,3 +2,5 @@ cmake*
.cache .cache
build build
compile_commands.json compile_commands.json
site/
web.sh

View File

@ -139,7 +139,8 @@ void bintree_init(BinTree *tree, void (*destroy)(void *data))
### bintree_destroy ### bintree_destroy
Destroys the nodes inside a tree and calls the deallaction function on the data if one was provided. Does not deallocate the tree itself, that is left to the user Destroys the nodes inside a tree and calls the deallaction function on the data if one was provided. Does not deallocate
the tree itself, that is left to the user.
```c ```c
void bintree_destroy(BinTree *tree) void bintree_destroy(BinTree *tree)
@ -147,7 +148,7 @@ void bintree_destroy(BinTree *tree)
### bintree_ins_left ### bintree_ins_left
Creates a new node containing `data` and inserts it as the left child of `node` Creates a new node containing `data` and inserts it as the left child of `node`.
```c ```c
int bintree_ins_left(BinTree *tree, BinTreeNode *node, void *data) int bintree_ins_left(BinTree *tree, BinTreeNode *node, void *data)
@ -163,7 +164,7 @@ int bintree_ins_right(BinTree *tree, BinTreeNode *node, void *data)
### bintree_rem_left ### bintree_rem_left
Removes and deallocates the left child node of `node`. Calls the deallocation function on the data if one was provided Removes and deallocates the left child node of `node`. Calls the deallocation function on the data if one was provided.
```c ```c
void bintree_rem_left(BinTree *tree, BinTreeNode *node) void bintree_rem_left(BinTree *tree, BinTreeNode *node)
@ -171,7 +172,7 @@ void bintree_rem_left(BinTree *tree, BinTreeNode *node)
### bintree_rem_right ### bintree_rem_right
Removes and deallocates the right child node of `node`. Calls the deallocation function on the data if one was provided Removes and deallocates the right child node of `node`. Calls the deallocation function on the data if one was provided.
```c ```c
void bintree_rem_right(BinTree *tree, BinTreeNode *node) void bintree_rem_right(BinTree *tree, BinTreeNode *node)
@ -179,7 +180,7 @@ void bintree_rem_right(BinTree *tree, BinTreeNode *node)
### bintree_debug_print ### bintree_debug_print
Prints a representation of the tree to stdout. Gets very messy with large trees Prints a representation of the tree to stdout. Gets very messy with large trees.
```c ```c
void bintree_debug_print(BinTree *tree) void bintree_debug_print(BinTree *tree)
@ -187,7 +188,7 @@ void bintree_debug_print(BinTree *tree)
### bintree_is_eob ### bintree_is_eob
Utility macro that checks if the node is the End Of Branch Utility macro that checks if the node is the End Of Branch.
```c ```c
#define bintree_is_eob(node) ((node) == NULL) #define bintree_is_eob(node) ((node) == NULL)
@ -195,7 +196,7 @@ Utility macro that checks if the node is the End Of Branch
### bintree_is_leaf ### bintree_is_leaf
Utility macro that checks if a node has children Utility macro that checks if a node has children.
```c ```c
#define bintree_is_leaf(node) ((node)->left == NULL && (node)->right == NULL) #define bintree_is_leaf(node) ((node)->left == NULL && (node)->right == NULL)

View File

@ -84,5 +84,5 @@ void del_split(char **sp);
/* Usage */ /* Usage */
size_t sp_sz = 0; size_t sp_sz = 0;
char **sp = split("Delete Me!", &sp_sz, " "); char **sp = split("Delete Me!", &sp_sz, " ");
void del_split(char **sp); void del_split(sp);
``` ```

View File

@ -1,3 +1,222 @@
# lflinkedlist # lflinkedlist
Coming soon A dual sided linked list structure. Used as the foundation for many of the structures in `libflint`
## Usage
Create the list. The user is responsible for memory management of the `List` struct.
```c
List *list = malloc(sizeof(List));
```
After the tree is created, init it. The second argument on `bintree_init()` is an optional memory freeing function pointer
with signature `void (*destroy)(void *data)`. Use `free()` from the stdlib if you are creating the data with `malloc()`.
If allocation of your data is more complex, you can pass your own memory deallocation function as long as it fits the
signature.
In this example, we are passing `NULL` because all memory will be stack allocated.
```c
ll_init(list, NULL);
int i = 1;
int j = 2;
int k = 4;
```
Next, insert data into the list. Data can be inserted from either side of a node.
```c
ll_ins_next(list, list->head, (void *) &i);
ll_ins_next(list, list->tail, (void *) &j);
ll_ins_next(list, list->tail, (void *) &k);
/* List is now 1 2 4 */
```
Lists can have a node removed by either targeting the node directly or removing a node pointed to by the head or tail of
another node. The user is responsible for the memory management of the data inside the node, which is why a `void*` must
be supplied to hold the data. Since in this example our memory is stack allocated, we don't need to worry about freeing
the `void*` but one must still be supplied for the function to work.
```c
/* List is 1 2 4 */
/* node is the 2nd node in the list with value 2 */
ListNode *node = list->head;
/* void pointer to the data inside of the node */
void *data;
ll_remove(list, node, &data);
/* List is now 1 4 */
printf("Removed: %d\n", *((int *) data));
/* Prints "2" */
```
Here is an alternative example using `ll_remove_next()` instead of `ll_remove()`
```c
/* node is the 2nd node in the list with value 2 */
ListNode *node = list->head;
void *data; /* void pointer to the data inside of the node */
ll_remove_next(list, node, &data);
/* List is now 1 2 */
printf("Removed: %d\n", *((int *) data));
/* Prints "4" */
```
To destroy the list, first call `ll_destroy()` to free the nodes in the list and optionally run the destroy function
against the data stored in the list. Since this example is stack allocated and we passed `NULL` when creating the
list, no destroy function is run against the memory in the nodes. The list itself must be deleted with `free()`
```c
ll_destroy(list);
free(list);
```
Complete example:
```c
List *list = malloc(sizeof(List));
ll_init(list, NULL);
int i = 1;
int j = 2;
int k = 4;
ll_ins_next(list, list->head, (void *) &i);
ll_ins_next(list, list->tail, (void *) &j);
ll_ins_next(list, list->tail, (void *) &k);
printf("List: ");
print_ll(list);
void *data;
ll_remove_next(list, list->head, &data);
printf("List: ");
print_ll(list);
printf("Removed: %d\n", *((int *) data));
ll_destroy(list);
free(list);
```
## Structs
### List
Double ended linked list struct
```c
typedef struct {
size_t size;
void (*destroy)(void *data);
int (*match)(const void *a, const void *b);
struct ListNode *head;
struct ListNode *tail;
} List;
```
Members:
- `size`: How many nodes are in the list
- `destroy`: Optional deallocation function for member data. Use `NULL` if data is stack allocated
- `match`: Comparison function between data inside two nodes. This is not used by `List` itself, but is used in structures built on top of `List`
- `head`: Pointer to the `ListNode` at the head of the list
- `tail`: Pointer to the `ListNode` at the tail of the list
### ListNode
Node of the list
```c
typedef struct ListNode {
void *data;
struct ListNode *next;
struct ListNode *prev;
} ListNode;
```
Members:
- `data`: void pointer to the member data in the node
- `next`: Pointer to the `ListNode` before this node in the list
- `prev`: Pointer to the `ListNode` after this node in the list
## Functions
### ll_init
Initalize the list. User is responsible for freeing memory with `ll_destroy()`.
```c
void ll_init(List *list, void (*destroy)(void *data));
```
### ll_destroy
Destroys the nodes inside a list and calls the deallocation funciton on the data if one was provided. Does not destroy
the list itself, that is left up to the user.
```c
void ll_destroy(List *list);
```
### ll_ins_next
Creates a new node containing `data` and inserts it after `node`.
```c
int ll_ins_next(List *list, ListNode *node, const void *data);
```
### ll_ins_prev
Creates a new node containing `data` and inserts it before `node`.
```c
int ll_ins_prev(List *list, ListNode *node, const void *data);
```
### ll_remove
Removes and deallocates the node pointed to by `node`. The user is responsible for managing the contained data's memory,
as such the `destroy` function is **not** run by `ll_remove()`
```c
int ll_remove(List *list, ListNode *node, void **data);
```
### ll_remove_next
Removes and deallocates the node pointed to by `node`'s `tail` pointer. The user is responsible for managing the contained data's memory,
as such the `destroy` function is **not** run by `ll_remove_next()`
```c
int ll_remove_next(List *list, ListNode *node, void **data);
```
### ll_remove_prev
Removes and deallocates the node pointed to by `node`'s `head` pointer. The user is responsible for managing the contained data's memory,
as such the `destroy` function is **not** run by `ll_remove_prev()`
```c
int ll_remove_prev(List *list, ListNode *node, void **data);
```
## Macros
### LL_ITER
A utility macro that helps with iterating over an entire list. A `ListNode` pointer named `node` is created as part of
this macro and can be used to access the current node in the iteration, so be careful your own variable naming if you
intend to use `LL_ITER`.
```c
#define LL_ITER(list) for(ListNode *node = (list)->head; node != NULL; node = node->next)
/* Example with list of strings */
for LL_ITER(list) {
printf("%s\n", (char *)(node->data));
}
```