This commit is contained in:
2021-02-01 14:06:37 -08:00
commit 86be1e8de5
18 changed files with 750 additions and 0 deletions

163
src/binarytree.c Normal file
View File

@@ -0,0 +1,163 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "binarytree.h"
void bintree_init(struct BinTree *tree, void (*destroy)(void *data)) {
tree->size = 0;
tree->destroy = destroy;
tree->compare = NULL;
tree->root = NULL;
}
void bintree_destroy(struct BinTree *tree) {
bintree_rem_left(tree, NULL);
memset(tree, 0, sizeof(struct BinTree));
}
int bintree_ins_left(struct BinTree *tree, struct BinTreeNode *node, void *data) {
struct BinTreeNode *new_node;
struct BinTreeNode **pos;
if (node == NULL) {
if (tree->size > 0) {
return 1;
}
pos = &tree->root;
} else {
if (node->left != NULL) {
return -1;
}
pos = &node->left;
}
if ((new_node = malloc(sizeof(struct BinTreeNode))) == NULL) {
return 2;
}
new_node->data = data;
new_node->left = NULL;
new_node->right = NULL;
*pos = new_node;
tree->size += 1;
return 0;
}
int bintree_ins_right(struct BinTree *tree, struct BinTreeNode *node, void *data) {
struct BinTreeNode *new_node;
struct BinTreeNode **pos;
if (node == NULL) {
if (tree->size > 0) {
return 1;
}
pos = &tree->root;
} else {
if (node->right != NULL) {
return -1;
}
pos = &node->right;
}
if ((new_node = malloc(sizeof(struct BinTreeNode))) == NULL) {
return 2;
}
new_node->data = data;
new_node->left = NULL;
new_node->right = NULL;
*pos = new_node;
tree->size += 1;
return 0;
}
void bintree_rem_left(struct BinTree *tree, struct BinTreeNode *node) {
if (tree->size == 0) {
return;
}
struct BinTreeNode **pos;
if (node == NULL) {
pos = &tree->root;
} else {
pos = &node->left;
}
if (*pos != NULL) {
bintree_rem_left(tree, *pos);
bintree_rem_right(tree, *pos);
if (tree->destroy != NULL) {
tree->destroy((*pos)->data);
}
free(*pos);
*pos = NULL;
tree->size -= 1;
}
}
void bintree_rem_right(struct BinTree *tree, struct BinTreeNode *node) {
if (tree->size == 0) {
return;
}
struct BinTreeNode **pos;
if (node == NULL) {
pos = &tree->root;
} else {
pos = &node->right;
}
if (*pos != NULL) {
bintree_rem_left(tree, *pos);
bintree_rem_right(tree, *pos);
if (tree->destroy != NULL) {
tree->destroy((*pos)->data);
}
free(*pos);
*pos = NULL;
tree->size -= 1;
}
}
int bintree_merge(struct BinTree *merge, struct BinTree *left, struct BinTree *right, void *data) {
bintree_init(merge, left->destroy);
if (bintree_ins_left(merge, NULL, data) != 0) {
bintree_destroy(merge);
return -1;
}
merge->root->left = left->root;
merge->root->right = right->root;
left->root = NULL;
left->size = 0;
right->root = NULL;
right->size = 0;
return 0;
}
void print_node(char* prefix, struct BinTreeNode *node, int is_left, void (*pfunc)(void* data)) {
if (node != NULL) {
printf("%s%s", prefix, (is_left ? "├──" : "└──" ));
pfunc(node->data);
char new_prefix[64];
memset(new_prefix, 0, 64);
strcat(new_prefix, prefix);
strcat(new_prefix, (is_left == 1 ? "" : " "));
print_node(new_prefix, node->left, 1, pfunc);
print_node(new_prefix, node->right, 0, pfunc);
}
}
void bintree_debug_pfunc_int(void* data) {
int i = *((int*)data);
printf("%d\n", i);
}
void bintree_debug_print(struct BinTree *tree) {
print_node("", tree->root, 0, bintree_debug_pfunc_int);
}

122
src/linkedlist.c Normal file
View File

@@ -0,0 +1,122 @@
#include <string.h>
#include <stdlib.h>
#include "linkedlist.h"
void ll_init(struct List* list, void (*destroy)(void *data)) {
list->size = 0;
list->destroy = destroy;
list->head = NULL;
list->tail = NULL;
}
void ll_destroy(struct List* list) {
void* data;
while (list->size > 0) {
if (ll_remove(list, list->tail, (void**)&data) == 0 && list->destroy != NULL) {
list->destroy(data);
}
}
memset(list, 0, sizeof(struct List));
}
int ll_ins_next(struct List* list, struct ListNode* node, const void* data) {
struct ListNode* new_node;
if (node == NULL && list->size != 0) {
return -1;
}
if ((new_node = malloc(sizeof(struct ListNode))) == NULL) {
return -1;
}
new_node->data = (void*)data;
if (list->size == 0) {
list->head = new_node;
list->head->prev = NULL;
list->head->next = NULL;
list->tail = new_node;
} else {
new_node->next = node->next;
new_node->prev = node;
if (node->next == NULL) {
list->tail = new_node;
} else {
node->next->prev = new_node;
}
node->next = new_node;
}
list->size++;
return 0;
}
int ll_ins_prev(struct List* list, struct ListNode* node, const void* data) {
struct ListNode* new_node;
if (node == NULL && list->size != 0) {
return -1;
}
if ((new_node = malloc(sizeof(struct ListNode))) == NULL) {
return -1;
}
new_node->data = (void*)data;
if (list->size == 0) {
list->head = new_node;
list->head->prev = NULL;
list->head->next = NULL;
list->tail = new_node;
} else {
new_node->next = node;
new_node->prev = node->prev;
if (node->prev == NULL) {
list->head = new_node;
} else {
node->prev->next = new_node;
}
node->prev = new_node;
}
list->size++;
return 0;
}
int ll_remove(struct List* list, struct ListNode* node, void** data) {
if (node == NULL || list->size == 0) {
return -1;
}
*data = node->data;
if (node == list->head) {
list->head = node->next;
if (list->head == NULL) {
list->tail = NULL;
} else {
node->next->prev = NULL;
}
} else {
node->prev->next = node->next;
if (node->next == NULL) {
list->tail = node->prev;
} else {
node->next->prev = node->prev;
}
}
free(node);
list->size--;
return 0;
}
int ll_remove_next(struct List* list, struct ListNode* node, void** data) {
if (node->next == NULL) {
return -1;
}
return ll_remove(list, node->next, data);
}
int ll_remove_prev(struct List* list, struct ListNode* node, void** data) {
if (node->prev == NULL) {
return -1;
}
return ll_remove(list, node->prev, data);
}

124
src/set.c Normal file
View File

@@ -0,0 +1,124 @@
#include "set.h"
void set_init(struct Set* set, int (*match)(const void* a, const void* b),
void (*destroy)(void* data)) {
ll_init(set, destroy);
set->match = match;
}
void set_destroy(struct Set* set) {
ll_destroy(set);
}
int set_insert(struct Set* set, const void* data) {
if (set_is_member(set, data)) {
return 1;
}
return ll_ins_next(set, set->tail, data);
}
int set_remove(struct Set* set, void** data) {
struct ListNode* node = NULL;
for (node = set->head; node != NULL; node = node->next) {
if (set->match(*data, node->data)) {
break;
}
}
if (node == NULL) {
return -1;
}
return ll_remove_next(set, node, data);
}
int set_union(struct Set* setu, const struct Set* a, const struct Set* b) {
struct ListNode* node;
void* data;
set_init(setu, a->match, NULL);
for (node = a->head; node != NULL; node = node->next) {
data = node->data;
if (ll_ins_next(setu, setu->tail, data) != 0) {
set_destroy(setu);
return -1;
}
}
for (node = b->head; node != NULL; node = node->next) {
if (set_is_member(a, node->data)) {
continue;
}
data = node->data;
if (ll_ins_next(setu, setu->tail, data) != 0) {
set_destroy(setu);
return -1;
}
}
return 0;
}
int set_intersection(struct Set* seti, const struct Set* a, const struct Set* b) {
struct ListNode* node;
void* data;
set_init(seti, a->match, NULL);
for (node = a->head; node != NULL; node = node->next) {
data = node->data;
if (set_is_member(b, data)) {
if (ll_ins_next(seti, seti->tail, data)) {
set_destroy(seti);
return -1;
}
}
}
return 0;
}
int set_difference(struct Set* setd, const struct Set* a, const struct Set* b) {
struct ListNode* node;
void* data;
set_init(setd, a->match, NULL);
for (node = a->head; node != NULL; node = node->next) {
data = node->data;
if (!set_is_member(b, data)) {
if (ll_ins_next(setd, setd->tail, data)) {
set_destroy(setd);
return -1;
}
}
}
return 0;
}
int set_is_member(const struct Set* set, const void* data) {
for (struct ListNode* node = set->head; node != NULL; node = node->next) {
if (set->match(data, node->data)) {
return 1;
}
}
return 0;
}
int set_is_subset(const struct Set* a, const struct Set* b) {
if (a->size > b->size) {
return 0;
}
for (struct ListNode* node = a->head; node != NULL; node = node->next) {
if (!set_is_member(b, node->data)) {
return 0;
}
}
return 1;
}
int set_is_equal(const struct Set* a, const struct Set* b) {
if (a->size == b->size) {
return 0;
}
return set_is_subset(a, b);
}

25
src/stack.c Normal file
View File

@@ -0,0 +1,25 @@
#include "stack.h"
void stack_init(struct Stack* stack, void (*destroy)(void* data)) {
ll_init(stack, destroy);
}
void stack_destroy(struct Stack* stack) {
ll_destroy(stack);
}
int stack_push(struct Stack* stack, void *data) {
if (stack->size == 0) {
return ll_ins_next(stack, NULL, data);
} else {
return ll_ins_next(stack, stack->tail, data);
}
}
void *stack_peek(struct Stack *stack) {
return stack->tail == NULL ? NULL : stack->tail->data;
}
int stack_pop(struct Stack *stack, void **data) {
return ll_remove(stack, stack->tail, data);
}