2024-01-16 15:46:22 -05:00
|
|
|
//
|
|
|
|
// Created by william on 1/16/24.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <malloc.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include "linked_list.h"
|
|
|
|
|
2024-05-01 11:45:39 -04:00
|
|
|
LinkedList linked_list_init(bool circular) {
|
2024-01-16 15:46:22 -05:00
|
|
|
LinkedList list;
|
2024-05-01 11:45:39 -04:00
|
|
|
|
|
|
|
list.circular = circular;
|
|
|
|
list.size = 0;
|
2024-01-16 15:46:22 -05:00
|
|
|
list.head = NULL;
|
|
|
|
list.end = NULL;
|
2024-05-01 11:45:39 -04:00
|
|
|
list.current = NULL;
|
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
void linked_list_add(LinkedList *list, void *data) {
|
2024-05-01 11:45:39 -04:00
|
|
|
assert(list != NULL);
|
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
LinkedListNode *node = malloc(sizeof(LinkedListNode));
|
|
|
|
if (node == NULL) {
|
|
|
|
perror("Failed to allocate memory for linked list node");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
node->data = data;
|
|
|
|
node->previous = list->end;
|
|
|
|
|
|
|
|
if (list->head == NULL) {
|
|
|
|
list->head = node;
|
2024-05-01 11:45:39 -04:00
|
|
|
list->current = node;
|
2024-01-16 15:46:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if (list->end != NULL) {
|
|
|
|
list->end->next = node;
|
|
|
|
}
|
|
|
|
|
2024-05-01 11:45:39 -04:00
|
|
|
if (list->circular) {
|
|
|
|
node->next = list->head;
|
|
|
|
} else {
|
|
|
|
node->next = NULL;
|
|
|
|
}
|
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
list->end = node;
|
2024-05-01 11:45:39 -04:00
|
|
|
list->size++;
|
|
|
|
}
|
|
|
|
|
2024-05-10 14:03:08 -04:00
|
|
|
LinkedListNode *linked_list_next(LinkedList *list) {
|
2024-05-01 11:45:39 -04:00
|
|
|
assert(list != NULL);
|
|
|
|
|
|
|
|
if (list->head == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LinkedListNode *next = list->current->next;
|
|
|
|
list->current = next;
|
|
|
|
return next;
|
|
|
|
}
|
|
|
|
|
|
|
|
void linked_list_cursor_reset(LinkedList *list) {
|
|
|
|
assert(list != NULL);
|
|
|
|
|
|
|
|
list->current = list->head;
|
2024-01-16 15:46:22 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, void *), void *userdata) {
|
2024-05-01 11:45:39 -04:00
|
|
|
assert(list != NULL);
|
|
|
|
assert(predicate != NULL);
|
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
LinkedListNode *node = list->head;
|
|
|
|
|
|
|
|
while (node != NULL) {
|
|
|
|
if (predicate(node->data, userdata)) {
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
node = node->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2024-05-01 11:45:39 -04:00
|
|
|
LinkedListNode *linked_list_get_near(LinkedList *list, int(*compute_distance)(void *, void *), void *userdata) {
|
|
|
|
assert(list != NULL);
|
|
|
|
assert(compute_distance != NULL);
|
|
|
|
|
2024-04-03 23:03:35 -04:00
|
|
|
LinkedListNode *near_node = list->head;
|
|
|
|
|
2024-05-10 14:03:08 -04:00
|
|
|
// int current_distance = compute_distance(near_node->data, userdata);
|
|
|
|
// if (current_distance == 0) {
|
|
|
|
// return near_node;
|
|
|
|
// }
|
|
|
|
|
|
|
|
int current_distance = 0x7fffffff;
|
|
|
|
while (near_node->next != NULL && current_distance != 0) {
|
|
|
|
int next_distance = compute_distance(near_node->next->data, userdata);
|
|
|
|
if (next_distance > current_distance) {
|
|
|
|
break;
|
|
|
|
}
|
2024-04-08 14:19:59 -04:00
|
|
|
|
2024-05-10 14:03:08 -04:00
|
|
|
near_node = near_node->next;
|
|
|
|
current_distance = next_distance;
|
2024-04-08 14:19:59 -04:00
|
|
|
}
|
2024-04-03 23:03:35 -04:00
|
|
|
|
|
|
|
// After the loop, we have found the nearest node in the list, assuming there is only one point of convergence
|
|
|
|
return near_node;
|
|
|
|
}
|
|
|
|
|
2024-01-16 15:46:22 -05:00
|
|
|
void linked_list_uninit(LinkedList *list) {
|
|
|
|
assert(list != NULL);
|
|
|
|
|
|
|
|
LinkedListNode *node = list->head;
|
|
|
|
while (node != NULL) {
|
|
|
|
LinkedListNode *current_node = node;
|
|
|
|
node = node->next;
|
|
|
|
|
|
|
|
free(current_node->data);
|
|
|
|
free(current_node);
|
2024-05-01 11:45:39 -04:00
|
|
|
|
|
|
|
if (node == list->head) {
|
|
|
|
// The list may be circular, we don't want an infinite free loop
|
|
|
|
break;
|
|
|
|
}
|
2024-01-16 15:46:22 -05:00
|
|
|
}
|
|
|
|
}
|