Push the WIP graphs handling code
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Mon, 16 Oct 2017 10:59:08 +0000 (12:59 +0200)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Mon, 16 Oct 2017 10:59:08 +0000 (12:59 +0200)
Not working yet

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
.gitignore
TP7/exo1/Makefile [new file with mode: 0644]
TP7/exo1/graphs.c [new file with mode: 0644]
TP7/exo1/graphs.h [new file with mode: 0644]
TP7/exo1/list.h [new file with mode: 0644]
TP7/exo1/main.c [new file with mode: 0644]

index af82068c2c849bd10bd9a2d0d71def66046cdbc0..33f33d35c4249301eddfd7ad4b30f453963a5c8b 100644 (file)
@@ -25,6 +25,7 @@ tas
 *.swp
 *~
 
+*.gch
 .build
 
 thumbs.db
diff --git a/TP7/exo1/Makefile b/TP7/exo1/Makefile
new file mode 100644 (file)
index 0000000..9870729
--- /dev/null
@@ -0,0 +1,82 @@
+# Sample Makefile to build simple project.
+#
+# This Makefile expect all source files (.c) to be at the same level, in the
+# current working directory.
+#
+# It will automatically generate dependencies, compile all files, and produce a
+# binary using the provided name.
+#
+# Set BINARY_NAME to the name of the binary file to build.
+# Set BUILD_TYPE to either debug or release
+#
+# Automatic dependencies code from:
+# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
+BINARY_NAME=exo1
+BUILD_TYPE=debug
+
+# ====================================
+# DO NOT CHANGE STUFF BEYOND THIS LINE
+# ====================================
+
+all: $(BINARY_NAME)
+
+CC=gcc
+LD=gcc
+
+WARN_FLAGS = -Wall -Wextra
+STD_FLAG = -std=c11
+
+ifeq ($(BUILD_TYPE),debug)
+BUILDDIR := .build/debug
+DEBUG_FLAG = -g
+STRIP_FLAG =
+OPTI_FLAG = -O0
+else
+BUILDDIR := .build/release
+DEBUG_FLAG =
+STRIP_FLAG = -s
+OPTI_FLAG = -O3
+endif
+
+CFLAGS := $(CFLAGS) $(WARN_FLAGS) $(STD_FLAG) $(OPTI_FLAG) $(DEBUG_FLAG)
+LDFLAGS := $(LDFLAGS) $(STRIP_FLAG)
+
+OBJDIR := $(BUILDDIR)/objs
+$(shell mkdir -p $(OBJDIR))
+
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
+
+DEPDIR := $(BUILDDIR)/deps
+$(shell mkdir -p $(DEPDIR))
+DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
+POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
+
+$(BINARY_NAME): $(OBJS)
+       @echo "[LD ] $@"
+       @$(LD) $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS) -o $@
+
+$(OBJDIR)/%.o: %.c $(DEPDIR)/%.d
+       @echo "[C  ] $*"
+       @$(CC) $(DEPFLAGS) $(CFLAGS) -c $< -o $@
+       @$(POSTCOMPILE)
+
+$(DEPDIR)/%.d: ;
+
+.PRECIOUS: $(DEPDIR)/%.d
+
+include $(wildcard $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS))))
+
+run:
+       ./$(BINARY_NAME)
+
+clean:
+       @echo "[CLN]"
+       -@rm -r $(BUILDDIR)
+       -@rm $(BINARY_NAME)
+
+disassemble: $(BINARY_NAME)
+       objdump -d $< | less
+
+symbols: $(BINARY_NAME)
+       objdump -t $< | sort | less
diff --git a/TP7/exo1/graphs.c b/TP7/exo1/graphs.c
new file mode 100644 (file)
index 0000000..4347350
--- /dev/null
@@ -0,0 +1,110 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "graphs.h"
+
+void init_adj_matrix(int adj_matrix[num_nodes][num_nodes]) {
+    for (unsigned int i = 0; i < num_nodes; i++) {
+        for (unsigned int j = 0; j < num_nodes; j++) {
+            adj_matrix[i][j] = 0;
+        }
+    }
+}
+
+unsigned int num_successors_adj_matrix(unsigned int node, int adj_matrix[num_nodes][num_nodes]) {
+    unsigned int num_successors = 0;
+
+    for (unsigned int i = 0; i < num_nodes; i++) {
+        if (adj_matrix[node][i] == 1) {
+            num_successors++;
+        }
+    }
+    return num_successors;
+}
+
+unsigned int num_successors_adj_list(unsigned int node, succ_list_t* nodes[num_nodes]) {
+    struct list_head* list_iter = NULL;
+    unsigned int num_successors = 0;
+
+    if (!list_empty(&nodes[node]->list)) {
+        list_for_each(list_iter, &nodes[node]->list) {
+            num_successors++;
+        }
+    }
+    return num_successors;
+}
+
+bool has_successor_adj_matrix(unsigned int node, int adj_matrix[num_nodes][num_nodes]) {
+
+    for (unsigned int i = 0; i < num_nodes; i++) {
+        if (adj_matrix[node][i] == 1) {
+            return true;
+        }
+    }
+    return false;
+}
+
+void add_adj_list_cell(unsigned int node, bool is_valued, int value, succ_list_t* successors_list) {
+    succ_list_t* list_cell = (succ_list_t*)malloc(sizeof(succ_list_t));
+    if (!list_cell) {
+        exit(EXIT_FAILURE);
+    }
+
+    list_cell->num_node = node;
+    if (is_valued) list_cell->val = value;
+    list_add_tail(&(list_cell->list), &(successors_list->list));
+}
+
+void free_adj_list(succ_list_t* successors_list) {
+     succ_list_t* list_iter = NULL;
+
+     while (!list_empty(&successors_list->list)) {
+         list_iter = list_entry(successors_list->list.next, succ_list_t, list);
+         list_del(&(list_iter->list));
+         free(list_iter);
+     }
+}
+
+void build_adj_list(unsigned int node, int adj_matrix[num_nodes][num_nodes], succ_list_t* successors_list) {
+    unsigned int num_successors = 0;
+
+    num_successors = num_successors_adj_matrix(node, adj_matrix);
+
+    for (unsigned int i = 0; i < num_successors && num_successors != 0; i++) {
+        if (adj_matrix[node][i] == 1) {
+            add_adj_list_cell(node, false, 0, successors_list);
+        }
+    }
+}
+
+void convert_adj_matrix_to_adj_lists(int adj_matrix[num_nodes][num_nodes], succ_list_t* nodes[num_nodes]) {
+    succ_list_t succ_list_array[num_nodes];
+
+    for (unsigned int i = 0; i < num_nodes; i++) {
+        //init num_nodes linked list
+        INIT_LIST_HEAD(&(succ_list_array[i].list));
+        //NOTE: the nodes array is NOT the head of the list, they point to the list head
+        build_adj_list(i, adj_matrix, &succ_list_array[i]);
+        //if list_array[i] not empty, then nodes[i] = &list_array[i] else = NULL
+    }
+}
+
+void display_adj_matrix(int adj_matrix[num_nodes][num_nodes]) {
+    for (unsigned int i = 0; i < num_nodes; i++) {
+        for (unsigned int j = 0; j < num_nodes; j++) {
+            printf("%d     ", adj_matrix[i][j]);
+        }
+        printf("\n");
+    }
+}
+
+void display_adj_lists(succ_list_t* nodes[num_nodes]) {
+    succ_list_t* list_iter = NULL;
+
+    for (unsigned int i = 0; i < num_nodes; i++) {
+        list_for_each_entry(list_iter, &nodes[i]->list, list) {
+            printf("%d     ", list_iter->num_node);
+        }
+        printf("\n");
+    }
+}
diff --git a/TP7/exo1/graphs.h b/TP7/exo1/graphs.h
new file mode 100644 (file)
index 0000000..734b96f
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef GRAPHS_H
+#define GRAPHS_H
+
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "list.h"
+
+/* number of nodes or vertices or points */
+//const unsigned int num_nodes = 10;
+#define num_nodes 5
+
+/* Adjacency matrix */
+/* for a valued graph */
+int M[num_nodes][num_nodes];
+/* for an oriented graph */
+//bool M[num_nodes][num_nodes];
+
+/* Adjacency list */
+typedef struct succ_list_s {
+    unsigned int num_node;
+    int val;
+    struct list_head list;
+} succ_list_t;
+//succ_list_t* nodes[num_nodes] = { NULL };
+
+void display_adj_matrix(int adj_matrix[num_nodes][num_nodes]);
+void convert_adj_matrix_to_adj_lists(int adj_matrix[num_nodes][num_nodes], succ_list_t* nodes[num_nodes]);
+void display_adj_lists(succ_list_t* nodes[num_nodes]);
+
+#endif
diff --git a/TP7/exo1/list.h b/TP7/exo1/list.h
new file mode 100644 (file)
index 0000000..b9d8cba
--- /dev/null
@@ -0,0 +1,246 @@
+#ifndef __LIST_H
+#define __LIST_H
+
+/* This file is from Linux Kernel (include/linux/list.h)
+ * and modified by simply removing hardware prefetching of list items.
+ * Here by copyright, credits attributed to wherever they belong.
+ * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu)
+ */
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+#define typeof __typeof__
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr) do { \
+       (ptr)->next = (ptr); (ptr)->prev = (ptr); \
+} while (0)
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+       next->prev = new;
+       new->next = next;
+       new->prev = prev;
+       prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+       __list_add(new, head, head->next);
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+       __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head *prev, struct list_head *next)
+{
+       next->prev = prev;
+       prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty on entry does not return true after this, the entry is in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+       __list_del(entry->prev, entry->next);
+       entry->next = (void *) 0;
+       entry->prev = (void *) 0;
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+       __list_del(entry->prev, entry->next);
+       INIT_LIST_HEAD(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+                                 struct list_head *head)
+{
+        __list_del(list->prev, list->next);
+        list_add_tail(list, head);
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(struct list_head *head)
+{
+       return head->next == head;
+}
+
+static inline void __list_splice(struct list_head *list,
+                                struct list_head *head)
+{
+       struct list_head *first = list->next;
+       struct list_head *last = list->prev;
+       struct list_head *at = head->next;
+
+       first->prev = head;
+       head->next = first;
+
+       last->next = at;
+       at->prev = last;
+}
+
+/**
+ * list_splice - join two lists
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(struct list_head *list, struct list_head *head)
+{
+       if (!list_empty(list))
+               __list_splice(list, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+                                   struct list_head *head)
+{
+       if (!list_empty(list)) {
+               __list_splice(list, head);
+               INIT_LIST_HEAD(list);
+       }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:       the &struct list_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+       ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
+
+/**
+ * list_for_each       -       iterate over a list
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @head:      the head for your list.
+ */
+#define list_for_each(pos, head) \
+       for (pos = (head)->next; pos != (head); \
+               pos = pos->next)
+/**
+ * list_for_each_prev  -       iterate over a list backwards
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @head:      the head for your list.
+ */
+#define list_for_each_prev(pos, head) \
+       for (pos = (head)->prev; pos != (head); \
+               pos = pos->prev)
+
+/**
+ * list_for_each_safe  -       iterate over a list safe against removal of list entry
+ * @pos:       the &struct list_head to use as a loop counter.
+ * @n:         another &struct list_head to use as temporary storage
+ * @head:      the head for your list.
+ */
+#define list_for_each_safe(pos, n, head) \
+       for (pos = (head)->next, n = pos->next; pos != (head); \
+               pos = n, n = pos->next)
+
+/**
+ * list_for_each_entry -       iterate over list of given type
+ * @pos:       the type * to use as a loop counter.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)                         \
+       for (pos = list_entry((head)->next, typeof(*pos), member);      \
+            &pos->member != (head);                                    \
+            pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos:       the type * to use as a loop counter.
+ * @n:         another type * to use as temporary storage
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member)                 \
+       for (pos = list_entry((head)->next, typeof(*pos), member),      \
+               n = list_entry(pos->member.next, typeof(*pos), member); \
+            &pos->member != (head);                                    \
+            pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+
+#endif
diff --git a/TP7/exo1/main.c b/TP7/exo1/main.c
new file mode 100644 (file)
index 0000000..883865b
--- /dev/null
@@ -0,0 +1,25 @@
+#include <stdio.h>
+
+#include "graphs.h"
+
+int main() {
+    int adj_matrix[num_nodes][num_nodes] = {
+                                             {0, 0, 0, 1, 0},
+                                             {0, 0, 1, 0, 0},
+                                             {0, 0, 0, 0, 0},
+                                             {0, 1, 0, 0, 1},
+                                             {1, 1, 1, 0, 0}
+                                           };
+    succ_list_t* nodes[num_nodes] = { NULL };
+    for (unsigned int i = 0; i < num_nodes; i++) {
+        LIST_HEAD(nodes);
+    }
+
+    display_adj_matrix(adj_matrix);
+
+    convert_adj_matrix_to_adj_lists(adj_matrix, nodes);
+
+    display_adj_lists(nodes);
+
+    return 0;
+}