]> www.ljiriste.work Git - Libft.git/commitdiff
Implement graph structure
authorLukáš Jiřiště <redacted>
Tue, 30 Dec 2025 14:28:47 +0000 (15:28 +0100)
committerLukáš Jiřiště <redacted>
Tue, 30 Dec 2025 14:28:47 +0000 (15:28 +0100)
Makefile
ft_struct/ft_graph.c [new file with mode: 0644]
ft_struct/ft_graph_helpers.c [new file with mode: 0644]
inc/ft_struct.h

index 91f244cc7e4f32c6ced6878101d90f817072bed1..e31ed4373187a63afdc10cc63cdf04f427d49535 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -49,6 +49,8 @@ SRCstruct:=   ft_stack_free.c                                                                                 \
                        ft_dict_traversal.c                                                                             \
                        ft_linked_list.c                                                                                \
                        ft_linked_list_helpers.c                                                                \
+                       ft_graph.c                                                                                              \
+                       ft_graph_helpers.c                                                                              \
 
 SRCparse:=     ft_parse.c                                                                                              \
                        ft_parsing_table_init.c                                                                 \
diff --git a/ft_struct/ft_graph.c b/ft_struct/ft_graph.c
new file mode 100644 (file)
index 0000000..f06bf4e
--- /dev/null
@@ -0,0 +1,58 @@
+#include "ft_struct.h"
+
+t_ft_stat      ft_graph_init(t_graph *graph, size_t el_size)
+{
+       if (!graph)
+               return (invalid_input);
+       graph->el_size = el_size;
+       return (ft_linked_list_init(&graph->nodes, sizeof(t_graph_node) + el_size));
+}
+
+// Static global function pointer would be more elegant
+static t_free_fun      handle_generic_free(int set, t_free_fun free_el)
+{
+       static t_free_fun       saved_free_el;
+
+       if (set)
+               saved_free_el = free_el;
+       return (saved_free_el);
+}
+
+static void    generic_free(void *element)
+{
+       t_graph_node    *node;
+       t_free_fun              free_el;
+
+       node = element;
+       free_el = handle_generic_free(0, NULL);
+       if (free_el)
+               free_el(ft_graph_access(node));
+       ft_vec_free(&node->connected_nodes, NULL);
+       return ;
+}
+
+void   ft_graph_free(t_graph *graph, t_free_fun free_el)
+{
+       if (!graph)
+               return ;
+       handle_generic_free(1, free_el);
+       ft_linked_list_free(&graph->nodes, generic_free);
+       return ;
+}
+
+void   ft_graph_delete(t_graph *graph, t_graph_node *node, t_free_fun free_el)
+{
+       t_graph_node            **disconnecting_node;
+       t_linked_list_node      *list_node;
+
+       while (node->connected_nodes.size > 0)
+       {
+               disconnecting_node = ft_vec_access(&node->connected_nodes, 0);
+               ft_graph_disconnect(node, *disconnecting_node);
+       }
+       handle_generic_free(1, free_el);
+       list_node = (t_linked_list_node *)
+               ((char *)node - offsetof(t_linked_list_node, data));
+       ft_linked_list_delete(&graph->nodes, list_node, generic_free);
+       return ;
+}
diff --git a/ft_struct/ft_graph_helpers.c b/ft_struct/ft_graph_helpers.c
new file mode 100644 (file)
index 0000000..30cb8ba
--- /dev/null
@@ -0,0 +1,54 @@
+#include "ft_struct.h"
+#include "libft.h"
+
+t_graph_node   *ft_graph_insert(t_graph *graph, void *element)
+{
+       t_graph_node    new_node;
+
+       if (!graph || !element)
+               return (NULL);
+       if (ft_vec_init(&new_node.connected_nodes, sizeof(t_graph_node *)))
+               return (NULL);
+       ft_memcpy(&new_node.data, element, graph->el_size);
+       return ((t_graph_node *)
+               &ft_linked_list_insert(&graph->nodes, &new_node)->data);
+}
+
+void   *ft_graph_access(t_graph_node *node)
+{
+       return (&node->data);
+}
+
+t_ft_stat      ft_graph_connect(t_graph_node *node1, t_graph_node *node2)
+{
+       t_ft_stat       res;
+
+       res = ft_vec_append(&node1->connected_nodes, &node2);
+       if (res != success)
+               return (res);
+       res = ft_vec_append(&node2->connected_nodes, &node1);
+       if (res != success)
+               ft_vec_forget(&node1->connected_nodes, node1->connected_nodes.size - 1);
+       return (res);
+}
+
+static int     cmp_address(const void *v_address1, const void *v_address2)
+{
+       t_graph_node *const     *address1;
+       t_graph_node *const     *address2;
+
+       address1 = v_address1;
+       address2 = v_address2;
+       return ((*address1 > *address2) - (*address1 < *address2));
+}
+
+void   ft_graph_disconnect(t_graph_node *node1, t_graph_node *node2)
+{
+       size_t  index;
+
+       ft_vec_find_index(&node1->connected_nodes, node2, &index, cmp_address);
+       ft_vec_forget(&node1->connected_nodes, index);
+       ft_vec_find_index(&node2->connected_nodes, node1, &index, cmp_address);
+       ft_vec_forget(&node2->connected_nodes, index);
+       return ;
+}
index debad500b156fed0c642629d3a19c292b359cc78..53e1db757818a20050cab28f3fa603777ddbae7a 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2024/06/20 16:59:43 by ljiriste          #+#    #+#             */
-/*   Updated: 2025/12/30 09:43:24 by ljiriste         ###   ########.fr       */
+/*   Updated: 2025/12/30 15:01:59 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -174,6 +174,28 @@ void                                       ft_linked_list_delete_next(
                                                        t_linked_list_node *node, t_free_fun free_el);
 void                                   ft_linked_list_free(t_linked_list *list, t_free_fun free_el);
 
+typedef struct s_graph_node
+{
+       t_vec   connected_nodes;
+       char    data[];
+}                      t_graph_node;
+
+// A linked list is used for storage so that node addresses stay constant
+typedef struct s_graph
+{
+       size_t                  el_size;
+       t_linked_list   nodes;
+}                                      t_graph;
+
+t_ft_stat              ft_graph_init(t_graph *graph, size_t el_size);
+t_graph_node   *ft_graph_insert(t_graph *graph, void *element);
+void                   *ft_graph_access(t_graph_node *node);
+t_ft_stat              ft_graph_connect(t_graph_node *node1, t_graph_node *node2);
+void                   ft_graph_disconnect(t_graph_node *node1, t_graph_node *node2);
+void                   ft_graph_delete(t_graph *graph, t_graph_node *node,
+                                       t_free_fun free_el);
+void                   ft_graph_free(t_graph *graph, t_free_fun free_el);
+
 # ifdef __cplusplus
 }
 # endif // __cplusplus