123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- /*!
- Temelia - Linked list implementation structure graph
- Copyright (C) 2008 Ceata (http://ceata.org/proiecte/temelia)
- @author Dascalu Laurentiu
- This program is free software; you can redistribute it and
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 3
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
- #include "include/graph.h"
- #include "include/graph_list.h"
- #include "include/linked_list.h"
- #include "include/vector.h"
- #include "include/pair.h"
- #include <stdlib.h>
- struct _graph_list_t
- {
- int size;
- vector_t adjacency_list;
- };
- typedef struct _graph_list_t *graph_list_t;
- void *graph_list_new(int size)
- {
- graph_list_t graph;
- int i;
- LOGGER("[graph list new] size %d\n", size);
- _ASSERT(size, <=, 0, NULL_POINTER, NULL);
- graph = (graph_list_t) _new(sizeof(struct _graph_list_t));
- _ASSERT(graph, ==, NULL, NULL_POINTER, NULL);
- graph->size = size;
- graph->adjacency_list = vector_new(size);
- for (i = 0; i < size; i++)
- vector_push_back(graph->adjacency_list, linked_list_new());
- if (graph->adjacency_list == NULL)
- {
- _delete(graph);
- return NULL;
- }
- return graph;
- }
- void graph_list_delete(void *graph)
- {
- graph_list_t m_graph = (graph_list_t) graph;
- int i;
- LOGGER("[graph list delete] graph %p, list %p\n", graph,
- m_graph->adjacency_list);
- _ASSERT(m_graph, ==, NULL, NULL_POINTER, );
- for (i = 0; i < m_graph->size; i++)
- linked_list_delete(vector_get_key_at(m_graph->adjacency_list, i));
- vector_delete(m_graph->adjacency_list);
- _delete(m_graph);
- }
- void graph_list_resize(void *graph, int size)
- {
- graph_list_t m_graph = (graph_list_t) graph;
- LOGGER("[graph list resize] graph %p, size %d\n", graph, size);
- _ASSERT(graph, ==, NULL, NULL_POINTER,);
- _ASSERT(size, <=, 0, INVALID_INPUT,);
- vector_set_size(m_graph->adjacency_list, size);
- m_graph->size = size;
- }
- static int _edge_compare_by_dest(void *key1, void *key2, void *context)
- {
- edge_t key;
- unsigned int dest;
- // Choose non-NULL pointer between key1 and key2
- if (key1 == NULL)
- key = key2;
- else
- key = key1;
- dest = *(unsigned int *) context;
- if (vertex_get_identifier(edge_get_vertex2(key)) == dest)
- return 0;
- return -1;
- }
- void graph_list_add_edge(void *graph, unsigned int src, unsigned int dest,
- edge_t edge)
- {
- graph_list_t m_graph = (graph_list_t) graph;
- linked_list_t m_list;
- LOGGER(
- "[graph list add edge] graph %p, source %u, destination %u, edge %p\n",
- graph, src, dest, edge);
- _ASSERT(graph, ==, NULL, NULL_POINTER,);
- _ASSERT(edge, ==, NULL, NULL_POINTER,);
- _ASSERT(src, >=, (unsigned int) m_graph->size, INVALID_INPUT,);
- _ASSERT(dest, >=, (unsigned int) m_graph->size, INVALID_INPUT,);
- m_list = vector_get_key_at(m_graph->adjacency_list, src);
- if (linked_list_search_key(m_list, NULL, _edge_compare_by_dest, &dest)
- == NULL)
- linked_list_push_back(m_list, edge);
- }
- edge_t graph_list_remove_edge(void *graph, unsigned int vertex1,
- unsigned int vertex2)
- {
- graph_list_t m_graph = (graph_list_t) graph;
- linked_list_t m_list;
- linked_list_iterator_t m_it;
- void *m_edge;
- LOGGER("[graph matrix remove edge] graph %p, source %u, destination %u\n",
- graph, vertex1, vertex2);
- _ASSERT(graph, ==, NULL, NULL_POINTER, NULL);
- _ASSERT(vertex1, >=, (unsigned int) m_graph->size, INVALID_INPUT, NULL);
- _ASSERT(vertex2, >=, (unsigned int) m_graph->size, INVALID_INPUT, NULL);
- m_list = vector_get_key_at(m_graph->adjacency_list, vertex1);
- m_it = linked_list_remove_key(m_list, NULL, _edge_compare_by_dest,
- &vertex2, 0);
- if (m_it == NULL)
- return NULL;
- m_edge = linked_list_iterator_get_key(m_it);
- linked_list_iterator_delete(m_it);
- return m_edge;
- }
- edge_t graph_list_get_edge(void *graph, unsigned int vertex1,
- unsigned int vertex2)
- {
- graph_list_t m_graph = (graph_list_t) graph;
- linked_list_t m_list;
- linked_list_iterator_t m_it;
- LOGGER("[graph list get edge] graph %p, vertex1 %u, vertex2 %u\n", graph,
- vertex1, vertex2);
- _ASSERT(graph, ==, NULL, NULL_POINTER, NULL);
- _ASSERT(vertex1, >=, (unsigned int) m_graph->size, INVALID_INPUT, NULL);
- _ASSERT(vertex2, >=, (unsigned int) m_graph->size, INVALID_INPUT, NULL);
- m_list = vector_get_key_at(m_graph->adjacency_list, vertex1);
- m_it
- = linked_list_search_key(m_list, NULL, _edge_compare_by_dest,
- &vertex2);
- if (m_it == NULL)
- return NULL;
- return linked_list_iterator_get_key(m_it);
- }
- vertex_t graph_list_first_vertex(void *graph, unsigned int vertex,
- void **context)
- {
- graph_list_t m_graph = (graph_list_t) graph;
- linked_list_iterator_t it;
- _ASSERT(graph, ==, NULL, NULL_POINTER, NULL);
- _ASSERT(vertex, >=, m_graph->size, NULL_POINTER, NULL);
- _ASSERT(context, ==, NULL, NULL_POINTER, NULL);
- it = linked_list_get_begin(vector_get_key_at(m_graph->adjacency_list,
- vertex));
- if (it == NULL)
- {
- *(linked_list_iterator_t *) context = NULL;
- return NULL;
- }
- *(linked_list_iterator_t *) context = linked_list_iterator_get_next(it);
- return edge_get_vertex2(linked_list_iterator_get_key(it));
- }
- void graph_list_delete_vertex_context(void **context)
- {
- }
- vertex_t graph_list_next_vertex(void *graph, unsigned int vertex_id,
- void **context)
- {
- linked_list_iterator_t *p_it = (linked_list_iterator_t *) context;
- linked_list_iterator_t it;
- vertex_t vertex;
- _ASSERT(p_it, ==, NULL, NULL_POINTER, NULL);
- it = *p_it;
- if (it)
- {
- vertex = edge_get_vertex2(linked_list_iterator_get_key(it));
- it = linked_list_iterator_get_next(it);
- *(linked_list_iterator_t *) context = it;
- return vertex;
- }
- *(linked_list_iterator_t *) context = NULL;
- return NULL;
- }
- edge_t graph_list_first_edge(void *graph, unsigned int vertex, void **context)
- {
- graph_list_t m_graph = (graph_list_t) graph;
- linked_list_iterator_t it;
- _ASSERT(graph, ==, NULL, NULL_POINTER, NULL);
- _ASSERT(vertex, >=, m_graph->size, NULL_POINTER, NULL);
- _ASSERT(context, ==, NULL, NULL_POINTER, NULL);
- it = linked_list_get_begin(vector_get_key_at(m_graph->adjacency_list,
- vertex));
- if (it == NULL)
- {
- *(linked_list_iterator_t *) context = NULL;
- return NULL;
- }
- *(linked_list_iterator_t *) context = linked_list_iterator_get_next(it);
- return linked_list_iterator_get_key(it);
- }
- void graph_list_delete_edge_context(void **context)
- {
- }
- edge_t graph_list_next_edge(void *graph, unsigned int vertex, void **context)
- {
- linked_list_iterator_t *p_it = (linked_list_iterator_t *) context;
- linked_list_iterator_t it;
- edge_t edge;
- _ASSERT(p_it, ==, NULL, NULL_POINTER, NULL);
- it = *p_it;
- if (it)
- {
- edge = linked_list_iterator_get_key(it);
- it = linked_list_iterator_get_next(it);
- *(linked_list_iterator_t *) context = it;
- return edge;
- }
- *(linked_list_iterator_t *) context = NULL;
- return NULL;
- }
- static void _iterate_vertex_key(void *key, void *context)
- {
- edge_t edge = (edge_t) key;
- void(*iterate_handler)(vertex_t src, vertex_t dest, double cost,
- char *label, void *key, int type) =
- (void(*)(vertex_t src, vertex_t dest, double cost, char *label,
- void *key, int type)) context;
- iterate_handler(edge_get_vertex1(edge), edge_get_vertex2(edge),
- edge_get_cost(edge), edge_get_label(edge), edge_get_key(edge),
- edge_get_type(edge));
- }
- static void _iterate_vertex_list(void *key, void *context)
- {
- linked_list_iterate(key, _iterate_vertex_key, context, -1);
- }
- void graph_list_iterate(void *graph, void(*iterate_handler)(vertex_t src,
- vertex_t dest, double cost, char *label, void *key, int type))
- {
- graph_list_t m_graph = (graph_list_t) graph;
- LOGGER("[graph list iterate] graph %p, iterate handler %d\n", graph,
- iterate_handler);
- _ASSERT(graph, ==, NULL, NULL_POINTER,);
- _ASSERT(iterate_handler, ==, NULL, NULL_POINTER,);
- vector_iterate(m_graph->adjacency_list, _iterate_vertex_list,
- (void *) iterate_handler);
- }
- static void _iterate_edge_list(void *key, void *context)
- {
- linked_list_t list;
- pair_t pair;
- list = (linked_list_t) key;
- pair = (pair_t) context;
- linked_list_iterate(list, pair_get_key(pair), pair_get_value(pair), -1);
- }
- void graph_list_iterate_edges(void *graph, void edge_handler(edge_t e,
- void *context), void *context)
- {
- graph_list_t m_graph = (graph_list_t) graph;
- pair_t pair;
- LOGGER(
- "[graph list iterate edges] graph %p, edge handler %p, context %p\n",
- graph, edge_handler, context);
- _ASSERT(graph, ==, NULL, NULL_POINTER,);
- _ASSERT(edge_handler, ==, NULL, NULL_POINTER,);
- pair = pair_new(edge_handler, context);
- _ASSERT(pair, ==, NULL, NULL_POINTER,);
- vector_iterate(m_graph->adjacency_list, _iterate_edge_list, pair);
- pair_delete(pair);
- }
- void graph_list_transpose(void *graph)
- {
- graph_list_t m_graph = (graph_list_t) graph;
- edge_t m_edge;
- vector_t adjacency_list;
- linked_list_t list;
- linked_list_iterator_t it;
- int i;
- LOGGER("[graph list transpose] graph %p\n", graph);
- _ASSERT(graph, ==, NULL, NULL_POINTER,);
- // Initialize new adjacency matrix
- adjacency_list = vector_new(m_graph->size);
- for (i = 0; i < m_graph->size; i++)
- vector_push_back(adjacency_list, linked_list_new());
- for (i = 0; i < m_graph->size; i++)
- {
- list = vector_get_key_at(m_graph->adjacency_list, i);
- for (it = linked_list_get_begin(list); it != NULL; it
- = linked_list_iterator_get_next(it))
- {
- // Aggregate modified edges into auxiliary adjacency list
- m_edge = linked_list_iterator_get_key(it);
- edge_switch_vertices(m_edge);
- linked_list_push_back(vector_get_key_at(adjacency_list,
- vertex_get_identifier(edge_get_vertex1(m_edge))), m_edge);
- }
- }
- // Delete the old adjacency matrix
- for (i = 0; i < m_graph->size; i++)
- linked_list_delete(vector_get_key_at(m_graph->adjacency_list, i));
- vector_delete(m_graph->adjacency_list);
- m_graph->adjacency_list = adjacency_list;
- }
- unsigned int graph_list_vertex_degree(void *graph, unsigned int vertex)
- {
- LOGGER("[graph list vertex degree] graph %p, vertex %u\n", graph, vertex);
- return graph_list_vertex_in_degree(graph, vertex)
- + graph_list_vertex_out_degree(graph, vertex);
- }
- unsigned int _vertex_in_degree(linked_list_t list, unsigned int vertex)
- {
- linked_list_iterator_t m_it;
- edge_t m_edge;
- unsigned int in_degree;
- _ASSERT(list, ==, NULL, NULL_POINTER, 0);
- m_it = linked_list_get_begin(list);
- in_degree = 0;
- while (m_it)
- {
- m_edge = linked_list_iterator_get_key(m_it);
- if (vertex_get_identifier(edge_get_vertex2(m_edge)) == vertex)
- in_degree++;
- m_it = linked_list_iterator_get_next(m_it);
- }
- return in_degree;
- }
- unsigned int graph_list_vertex_in_degree(void *graph, unsigned int vertex)
- {
- int i;
- unsigned int in_degree;
- graph_list_t m_graph = (graph_list_t) graph;
- LOGGER("[graph list in degree] graph %p, vertex %u\n", graph, vertex);
- _ASSERT(graph, ==, NULL, NULL_POINTER, -1);
- _ASSERT(vertex, >=, m_graph->size, INVALID_INPUT, -1);
- in_degree = 0;
- for (i = 0; i < m_graph->size; i++)
- {
- if (i != vertex)
- in_degree += _vertex_in_degree(vector_get_key_at(
- m_graph->adjacency_list, i), vertex);
- }
- return in_degree;
- }
- unsigned int graph_list_vertex_out_degree(void *graph, unsigned int vertex)
- {
- graph_list_t m_graph = (graph_list_t) graph;
- LOGGER("[graph list out degree] graph %p, vertex %u\n", graph, vertex);
- _ASSERT(graph, ==, NULL, NULL_POINTER, -1);
- _ASSERT(vertex, >=, m_graph->size, INVALID_INPUT, -1);
- return linked_list_get_size(vector_get_key_at(m_graph->adjacency_list,
- vertex));
- }
- unsigned int graph_list_dimension(void *graph)
- {
- int i, size;
- unsigned int dimension;
- linked_list_t list;
- graph_list_t m_graph = (graph_list_t) graph;
- LOGGER("[graph list dimension] graph %p\n", graph);
- _ASSERT(graph, ==, NULL, NULL_POINTER, -1);
- dimension = 0;
- size = vector_get_size(m_graph->adjacency_list);
- for (i = 0; i < size; i++)
- {
- list = vector_get_key_at(m_graph->adjacency_list, i);
- dimension += linked_list_get_size(list);
- }
- return dimension;
- }
- static void _delete_vertex_edges(void *key, void *context)
- {
- ((void(*)(edge_t edge)) context)(key);
- }
- void graph_list_delete_vertex_edges(void *graph, unsigned int vertex,
- void(*edge_delete)(edge_t edge))
- {
- linked_list_t m_list;
- linked_list_iterator_t it;
- graph_list_t m_graph = (graph_list_t) graph;
- int i;
- LOGGER(
- "[graph list delete vertex edges] graph %p, vertex %u, edge delete %p\n",
- graph, vertex, edge_delete);
- _ASSERT(graph, ==, NULL, NULL_POINTER,);
- _ASSERT(vertex, >=, m_graph->size, INVALID_INPUT,);
- _ASSERT(edge_delete, ==, NULL, NULL_POINTER,);
- m_list = vector_get_key_at(m_graph->adjacency_list, vertex);
- _ASSERT(m_list, ==, NULL, INVALID_INPUT,);
- linked_list_iterate(m_list, _delete_vertex_edges, edge_delete, 1);
- linked_list_delete(m_list);
- vector_set_key_at(m_graph->adjacency_list, vertex, linked_list_new());
- for (i = 0; i < m_graph->size; i++)
- {
- if (i != vertex)
- {
- m_list = vector_get_key_at(m_graph->adjacency_list, i);
- it = linked_list_remove_key(m_list, NULL, _edge_compare_by_dest,
- &vertex, 0);
- edge_delete(linked_list_iterator_get_key(it));
- linked_list_iterator_delete(it);
- }
- }
- }
- void graph_list_load(void *graph_src, void *graph_dest)
- {
- graph_list_t m_graph_src = (graph_list_t) graph_src;
- graph_list_t m_graph_dest = (graph_list_t) graph_dest;
- linked_list_t list_src, list_dest;
- linked_list_iterator_t it_src, it_dest;
- int i, size;
- _ASSERT(graph_src, ==, NULL, NULL_POINTER,);
- _ASSERT(graph_dest, ==, NULL, NULL_POINTER,);
- _ASSERT(m_graph_src->size, != , m_graph_dest->size, INVALID_INPUT,);
- size = m_graph_src->size;
- for (i = 0; i < size; i++)
- {
- list_src = vector_get_key_at(m_graph_src->adjacency_list, i);
- it_src = linked_list_get_begin(list_src);
- list_dest = vector_get_key_at(m_graph_dest->adjacency_list, i);
- it_dest = linked_list_get_back(list_dest);
- while (it_src)
- {
- linked_list_iterator_set_key(it_dest, linked_list_iterator_get_key(
- it_src));
- it_src = linked_list_iterator_get_next(it_src);
- }
- }
- }
- static void *_store_linked_list_clone(void *key, void *context)
- {
- return linked_list_clone(key, NULL, NULL);
- }
- void *graph_list_store(void *graph_src)
- {
- graph_list_t m_graph = (graph_list_t) graph_src;
- graph_list_t m_clone;
- _ASSERT(graph_src, ==, NULL, NULL_POINTER, NULL);
- m_clone = (graph_list_t) _new(sizeof(struct _graph_list_t));
- m_clone->size = m_graph->size;
- m_clone->adjacency_list = vector_clone(m_graph->adjacency_list,
- _store_linked_list_clone, NULL);
- return m_clone;
- }
- void graph_list_debug(void *graph)
- {
- graph_list_t m_graph = (graph_list_t) graph;
- linked_list_t list;
- linked_list_iterator_t it;
- int i, n;
- _ASSERT(graph, ==, NULL, NULL_POINTER,);
- n = m_graph->size;
- for (i = 0; i < n; i++)
- {
- list = vector_get_key_at(m_graph->adjacency_list, i);
- it = linked_list_get_begin(list);
- while (1)
- {
- if (it == NULL)
- break;
- edge_debug(linked_list_iterator_get_key(it), NULL);
- it = linked_list_iterator_get_next(it);
- }
- }
- }
- graph_implementation_t graph_list_get_implementation()
- {
- static struct _graph_implementation_t _graph_adjacency_list_implementation;
- _graph_adjacency_list_implementation.new_g = graph_list_new;
- _graph_adjacency_list_implementation.delete_g = graph_list_delete;
- _graph_adjacency_list_implementation.resize = graph_list_resize;
- _graph_adjacency_list_implementation.add_edge = graph_list_add_edge;
- _graph_adjacency_list_implementation.remove_edge = graph_list_remove_edge;
- _graph_adjacency_list_implementation.get_edge = graph_list_get_edge;
- _graph_adjacency_list_implementation.first_vertex = graph_list_first_vertex;
- _graph_adjacency_list_implementation.delete_vertex_context
- = graph_list_delete_vertex_context;
- _graph_adjacency_list_implementation.next_vertex = graph_list_next_vertex;
- _graph_adjacency_list_implementation.first_edge = graph_list_first_edge;
- _graph_adjacency_list_implementation.delete_edge_context
- = graph_list_delete_edge_context;
- _graph_adjacency_list_implementation.next_edge = graph_list_next_edge;
- _graph_adjacency_list_implementation.iterate_edges
- = graph_list_iterate_edges;
- _graph_adjacency_list_implementation.transpose = graph_list_transpose;
- _graph_adjacency_list_implementation.vertex_degree
- = graph_list_vertex_degree;
- _graph_adjacency_list_implementation.vertex_in_degree
- = graph_list_vertex_in_degree;
- _graph_adjacency_list_implementation.vertex_out_degree
- = graph_list_vertex_out_degree;
- _graph_adjacency_list_implementation.dimension = graph_list_dimension;
- _graph_adjacency_list_implementation.delete_vertex_edges
- = graph_list_delete_vertex_edges;
- _graph_adjacency_list_implementation.load = graph_list_load;
- _graph_adjacency_list_implementation.store = graph_list_store;
- _graph_adjacency_list_implementation.debug = graph_list_debug;
- return &_graph_adjacency_list_implementation;
- }
|