graph_list.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  1. /*!
  2. Temelia - Linked list implementation structure graph
  3. Copyright (C) 2008 Ceata (http://ceata.org/proiecte/temelia)
  4. @author Dascalu Laurentiu
  5. This program is free software; you can redistribute it and
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 3
  8. of the License, or (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  16. */
  17. #include "include/graph.h"
  18. #include "include/graph_list.h"
  19. #include "include/linked_list.h"
  20. #include "include/vector.h"
  21. #include "include/pair.h"
  22. #include <stdlib.h>
  23. struct _graph_list_t
  24. {
  25. int size;
  26. vector_t adjacency_list;
  27. };
  28. typedef struct _graph_list_t *graph_list_t;
  29. void *graph_list_new(int size)
  30. {
  31. graph_list_t graph;
  32. int i;
  33. LOGGER("[graph list new] size %d\n", size);
  34. _ASSERT(size, <=, 0, NULL_POINTER, NULL);
  35. graph = (graph_list_t) _new(sizeof(struct _graph_list_t));
  36. _ASSERT(graph, ==, NULL, NULL_POINTER, NULL);
  37. graph->size = size;
  38. graph->adjacency_list = vector_new(size);
  39. for (i = 0; i < size; i++)
  40. vector_push_back(graph->adjacency_list, linked_list_new());
  41. if (graph->adjacency_list == NULL)
  42. {
  43. _delete(graph);
  44. return NULL;
  45. }
  46. return graph;
  47. }
  48. void graph_list_delete(void *graph)
  49. {
  50. graph_list_t m_graph = (graph_list_t) graph;
  51. int i;
  52. LOGGER("[graph list delete] graph %p, list %p\n", graph,
  53. m_graph->adjacency_list);
  54. _ASSERT(m_graph, ==, NULL, NULL_POINTER, );
  55. for (i = 0; i < m_graph->size; i++)
  56. linked_list_delete(vector_get_key_at(m_graph->adjacency_list, i));
  57. vector_delete(m_graph->adjacency_list);
  58. _delete(m_graph);
  59. }
  60. void graph_list_resize(void *graph, int size)
  61. {
  62. graph_list_t m_graph = (graph_list_t) graph;
  63. LOGGER("[graph list resize] graph %p, size %d\n", graph, size);
  64. _ASSERT(graph, ==, NULL, NULL_POINTER,);
  65. _ASSERT(size, <=, 0, INVALID_INPUT,);
  66. vector_set_size(m_graph->adjacency_list, size);
  67. m_graph->size = size;
  68. }
  69. static int _edge_compare_by_dest(void *key1, void *key2, void *context)
  70. {
  71. edge_t key;
  72. unsigned int dest;
  73. // Choose non-NULL pointer between key1 and key2
  74. if (key1 == NULL)
  75. key = key2;
  76. else
  77. key = key1;
  78. dest = *(unsigned int *) context;
  79. if (vertex_get_identifier(edge_get_vertex2(key)) == dest)
  80. return 0;
  81. return -1;
  82. }
  83. void graph_list_add_edge(void *graph, unsigned int src, unsigned int dest,
  84. edge_t edge)
  85. {
  86. graph_list_t m_graph = (graph_list_t) graph;
  87. linked_list_t m_list;
  88. LOGGER(
  89. "[graph list add edge] graph %p, source %u, destination %u, edge %p\n",
  90. graph, src, dest, edge);
  91. _ASSERT(graph, ==, NULL, NULL_POINTER,);
  92. _ASSERT(edge, ==, NULL, NULL_POINTER,);
  93. _ASSERT(src, >=, (unsigned int) m_graph->size, INVALID_INPUT,);
  94. _ASSERT(dest, >=, (unsigned int) m_graph->size, INVALID_INPUT,);
  95. m_list = vector_get_key_at(m_graph->adjacency_list, src);
  96. if (linked_list_search_key(m_list, NULL, _edge_compare_by_dest, &dest)
  97. == NULL)
  98. linked_list_push_back(m_list, edge);
  99. }
  100. edge_t graph_list_remove_edge(void *graph, unsigned int vertex1,
  101. unsigned int vertex2)
  102. {
  103. graph_list_t m_graph = (graph_list_t) graph;
  104. linked_list_t m_list;
  105. linked_list_iterator_t m_it;
  106. void *m_edge;
  107. LOGGER("[graph matrix remove edge] graph %p, source %u, destination %u\n",
  108. graph, vertex1, vertex2);
  109. _ASSERT(graph, ==, NULL, NULL_POINTER, NULL);
  110. _ASSERT(vertex1, >=, (unsigned int) m_graph->size, INVALID_INPUT, NULL);
  111. _ASSERT(vertex2, >=, (unsigned int) m_graph->size, INVALID_INPUT, NULL);
  112. m_list = vector_get_key_at(m_graph->adjacency_list, vertex1);
  113. m_it = linked_list_remove_key(m_list, NULL, _edge_compare_by_dest,
  114. &vertex2, 0);
  115. if (m_it == NULL)
  116. return NULL;
  117. m_edge = linked_list_iterator_get_key(m_it);
  118. linked_list_iterator_delete(m_it);
  119. return m_edge;
  120. }
  121. edge_t graph_list_get_edge(void *graph, unsigned int vertex1,
  122. unsigned int vertex2)
  123. {
  124. graph_list_t m_graph = (graph_list_t) graph;
  125. linked_list_t m_list;
  126. linked_list_iterator_t m_it;
  127. LOGGER("[graph list get edge] graph %p, vertex1 %u, vertex2 %u\n", graph,
  128. vertex1, vertex2);
  129. _ASSERT(graph, ==, NULL, NULL_POINTER, NULL);
  130. _ASSERT(vertex1, >=, (unsigned int) m_graph->size, INVALID_INPUT, NULL);
  131. _ASSERT(vertex2, >=, (unsigned int) m_graph->size, INVALID_INPUT, NULL);
  132. m_list = vector_get_key_at(m_graph->adjacency_list, vertex1);
  133. m_it
  134. = linked_list_search_key(m_list, NULL, _edge_compare_by_dest,
  135. &vertex2);
  136. if (m_it == NULL)
  137. return NULL;
  138. return linked_list_iterator_get_key(m_it);
  139. }
  140. vertex_t graph_list_first_vertex(void *graph, unsigned int vertex,
  141. void **context)
  142. {
  143. graph_list_t m_graph = (graph_list_t) graph;
  144. linked_list_iterator_t it;
  145. _ASSERT(graph, ==, NULL, NULL_POINTER, NULL);
  146. _ASSERT(vertex, >=, m_graph->size, NULL_POINTER, NULL);
  147. _ASSERT(context, ==, NULL, NULL_POINTER, NULL);
  148. it = linked_list_get_begin(vector_get_key_at(m_graph->adjacency_list,
  149. vertex));
  150. if (it == NULL)
  151. {
  152. *(linked_list_iterator_t *) context = NULL;
  153. return NULL;
  154. }
  155. *(linked_list_iterator_t *) context = linked_list_iterator_get_next(it);
  156. return edge_get_vertex2(linked_list_iterator_get_key(it));
  157. }
  158. void graph_list_delete_vertex_context(void **context)
  159. {
  160. }
  161. vertex_t graph_list_next_vertex(void *graph, unsigned int vertex_id,
  162. void **context)
  163. {
  164. linked_list_iterator_t *p_it = (linked_list_iterator_t *) context;
  165. linked_list_iterator_t it;
  166. vertex_t vertex;
  167. _ASSERT(p_it, ==, NULL, NULL_POINTER, NULL);
  168. it = *p_it;
  169. if (it)
  170. {
  171. vertex = edge_get_vertex2(linked_list_iterator_get_key(it));
  172. it = linked_list_iterator_get_next(it);
  173. *(linked_list_iterator_t *) context = it;
  174. return vertex;
  175. }
  176. *(linked_list_iterator_t *) context = NULL;
  177. return NULL;
  178. }
  179. edge_t graph_list_first_edge(void *graph, unsigned int vertex, void **context)
  180. {
  181. graph_list_t m_graph = (graph_list_t) graph;
  182. linked_list_iterator_t it;
  183. _ASSERT(graph, ==, NULL, NULL_POINTER, NULL);
  184. _ASSERT(vertex, >=, m_graph->size, NULL_POINTER, NULL);
  185. _ASSERT(context, ==, NULL, NULL_POINTER, NULL);
  186. it = linked_list_get_begin(vector_get_key_at(m_graph->adjacency_list,
  187. vertex));
  188. if (it == NULL)
  189. {
  190. *(linked_list_iterator_t *) context = NULL;
  191. return NULL;
  192. }
  193. *(linked_list_iterator_t *) context = linked_list_iterator_get_next(it);
  194. return linked_list_iterator_get_key(it);
  195. }
  196. void graph_list_delete_edge_context(void **context)
  197. {
  198. }
  199. edge_t graph_list_next_edge(void *graph, unsigned int vertex, void **context)
  200. {
  201. linked_list_iterator_t *p_it = (linked_list_iterator_t *) context;
  202. linked_list_iterator_t it;
  203. edge_t edge;
  204. _ASSERT(p_it, ==, NULL, NULL_POINTER, NULL);
  205. it = *p_it;
  206. if (it)
  207. {
  208. edge = linked_list_iterator_get_key(it);
  209. it = linked_list_iterator_get_next(it);
  210. *(linked_list_iterator_t *) context = it;
  211. return edge;
  212. }
  213. *(linked_list_iterator_t *) context = NULL;
  214. return NULL;
  215. }
  216. static void _iterate_vertex_key(void *key, void *context)
  217. {
  218. edge_t edge = (edge_t) key;
  219. void(*iterate_handler)(vertex_t src, vertex_t dest, double cost,
  220. char *label, void *key, int type) =
  221. (void(*)(vertex_t src, vertex_t dest, double cost, char *label,
  222. void *key, int type)) context;
  223. iterate_handler(edge_get_vertex1(edge), edge_get_vertex2(edge),
  224. edge_get_cost(edge), edge_get_label(edge), edge_get_key(edge),
  225. edge_get_type(edge));
  226. }
  227. static void _iterate_vertex_list(void *key, void *context)
  228. {
  229. linked_list_iterate(key, _iterate_vertex_key, context, -1);
  230. }
  231. void graph_list_iterate(void *graph, void(*iterate_handler)(vertex_t src,
  232. vertex_t dest, double cost, char *label, void *key, int type))
  233. {
  234. graph_list_t m_graph = (graph_list_t) graph;
  235. LOGGER("[graph list iterate] graph %p, iterate handler %d\n", graph,
  236. iterate_handler);
  237. _ASSERT(graph, ==, NULL, NULL_POINTER,);
  238. _ASSERT(iterate_handler, ==, NULL, NULL_POINTER,);
  239. vector_iterate(m_graph->adjacency_list, _iterate_vertex_list,
  240. (void *) iterate_handler);
  241. }
  242. static void _iterate_edge_list(void *key, void *context)
  243. {
  244. linked_list_t list;
  245. pair_t pair;
  246. list = (linked_list_t) key;
  247. pair = (pair_t) context;
  248. linked_list_iterate(list, pair_get_key(pair), pair_get_value(pair), -1);
  249. }
  250. void graph_list_iterate_edges(void *graph, void edge_handler(edge_t e,
  251. void *context), void *context)
  252. {
  253. graph_list_t m_graph = (graph_list_t) graph;
  254. pair_t pair;
  255. LOGGER(
  256. "[graph list iterate edges] graph %p, edge handler %p, context %p\n",
  257. graph, edge_handler, context);
  258. _ASSERT(graph, ==, NULL, NULL_POINTER,);
  259. _ASSERT(edge_handler, ==, NULL, NULL_POINTER,);
  260. pair = pair_new(edge_handler, context);
  261. _ASSERT(pair, ==, NULL, NULL_POINTER,);
  262. vector_iterate(m_graph->adjacency_list, _iterate_edge_list, pair);
  263. pair_delete(pair);
  264. }
  265. void graph_list_transpose(void *graph)
  266. {
  267. graph_list_t m_graph = (graph_list_t) graph;
  268. edge_t m_edge;
  269. vector_t adjacency_list;
  270. linked_list_t list;
  271. linked_list_iterator_t it;
  272. int i;
  273. LOGGER("[graph list transpose] graph %p\n", graph);
  274. _ASSERT(graph, ==, NULL, NULL_POINTER,);
  275. // Initialize new adjacency matrix
  276. adjacency_list = vector_new(m_graph->size);
  277. for (i = 0; i < m_graph->size; i++)
  278. vector_push_back(adjacency_list, linked_list_new());
  279. for (i = 0; i < m_graph->size; i++)
  280. {
  281. list = vector_get_key_at(m_graph->adjacency_list, i);
  282. for (it = linked_list_get_begin(list); it != NULL; it
  283. = linked_list_iterator_get_next(it))
  284. {
  285. // Aggregate modified edges into auxiliary adjacency list
  286. m_edge = linked_list_iterator_get_key(it);
  287. edge_switch_vertices(m_edge);
  288. linked_list_push_back(vector_get_key_at(adjacency_list,
  289. vertex_get_identifier(edge_get_vertex1(m_edge))), m_edge);
  290. }
  291. }
  292. // Delete the old adjacency matrix
  293. for (i = 0; i < m_graph->size; i++)
  294. linked_list_delete(vector_get_key_at(m_graph->adjacency_list, i));
  295. vector_delete(m_graph->adjacency_list);
  296. m_graph->adjacency_list = adjacency_list;
  297. }
  298. unsigned int graph_list_vertex_degree(void *graph, unsigned int vertex)
  299. {
  300. LOGGER("[graph list vertex degree] graph %p, vertex %u\n", graph, vertex);
  301. return graph_list_vertex_in_degree(graph, vertex)
  302. + graph_list_vertex_out_degree(graph, vertex);
  303. }
  304. unsigned int _vertex_in_degree(linked_list_t list, unsigned int vertex)
  305. {
  306. linked_list_iterator_t m_it;
  307. edge_t m_edge;
  308. unsigned int in_degree;
  309. _ASSERT(list, ==, NULL, NULL_POINTER, 0);
  310. m_it = linked_list_get_begin(list);
  311. in_degree = 0;
  312. while (m_it)
  313. {
  314. m_edge = linked_list_iterator_get_key(m_it);
  315. if (vertex_get_identifier(edge_get_vertex2(m_edge)) == vertex)
  316. in_degree++;
  317. m_it = linked_list_iterator_get_next(m_it);
  318. }
  319. return in_degree;
  320. }
  321. unsigned int graph_list_vertex_in_degree(void *graph, unsigned int vertex)
  322. {
  323. int i;
  324. unsigned int in_degree;
  325. graph_list_t m_graph = (graph_list_t) graph;
  326. LOGGER("[graph list in degree] graph %p, vertex %u\n", graph, vertex);
  327. _ASSERT(graph, ==, NULL, NULL_POINTER, -1);
  328. _ASSERT(vertex, >=, m_graph->size, INVALID_INPUT, -1);
  329. in_degree = 0;
  330. for (i = 0; i < m_graph->size; i++)
  331. {
  332. if (i != vertex)
  333. in_degree += _vertex_in_degree(vector_get_key_at(
  334. m_graph->adjacency_list, i), vertex);
  335. }
  336. return in_degree;
  337. }
  338. unsigned int graph_list_vertex_out_degree(void *graph, unsigned int vertex)
  339. {
  340. graph_list_t m_graph = (graph_list_t) graph;
  341. LOGGER("[graph list out degree] graph %p, vertex %u\n", graph, vertex);
  342. _ASSERT(graph, ==, NULL, NULL_POINTER, -1);
  343. _ASSERT(vertex, >=, m_graph->size, INVALID_INPUT, -1);
  344. return linked_list_get_size(vector_get_key_at(m_graph->adjacency_list,
  345. vertex));
  346. }
  347. unsigned int graph_list_dimension(void *graph)
  348. {
  349. int i, size;
  350. unsigned int dimension;
  351. linked_list_t list;
  352. graph_list_t m_graph = (graph_list_t) graph;
  353. LOGGER("[graph list dimension] graph %p\n", graph);
  354. _ASSERT(graph, ==, NULL, NULL_POINTER, -1);
  355. dimension = 0;
  356. size = vector_get_size(m_graph->adjacency_list);
  357. for (i = 0; i < size; i++)
  358. {
  359. list = vector_get_key_at(m_graph->adjacency_list, i);
  360. dimension += linked_list_get_size(list);
  361. }
  362. return dimension;
  363. }
  364. static void _delete_vertex_edges(void *key, void *context)
  365. {
  366. ((void(*)(edge_t edge)) context)(key);
  367. }
  368. void graph_list_delete_vertex_edges(void *graph, unsigned int vertex,
  369. void(*edge_delete)(edge_t edge))
  370. {
  371. linked_list_t m_list;
  372. linked_list_iterator_t it;
  373. graph_list_t m_graph = (graph_list_t) graph;
  374. int i;
  375. LOGGER(
  376. "[graph list delete vertex edges] graph %p, vertex %u, edge delete %p\n",
  377. graph, vertex, edge_delete);
  378. _ASSERT(graph, ==, NULL, NULL_POINTER,);
  379. _ASSERT(vertex, >=, m_graph->size, INVALID_INPUT,);
  380. _ASSERT(edge_delete, ==, NULL, NULL_POINTER,);
  381. m_list = vector_get_key_at(m_graph->adjacency_list, vertex);
  382. _ASSERT(m_list, ==, NULL, INVALID_INPUT,);
  383. linked_list_iterate(m_list, _delete_vertex_edges, edge_delete, 1);
  384. linked_list_delete(m_list);
  385. vector_set_key_at(m_graph->adjacency_list, vertex, linked_list_new());
  386. for (i = 0; i < m_graph->size; i++)
  387. {
  388. if (i != vertex)
  389. {
  390. m_list = vector_get_key_at(m_graph->adjacency_list, i);
  391. it = linked_list_remove_key(m_list, NULL, _edge_compare_by_dest,
  392. &vertex, 0);
  393. edge_delete(linked_list_iterator_get_key(it));
  394. linked_list_iterator_delete(it);
  395. }
  396. }
  397. }
  398. void graph_list_load(void *graph_src, void *graph_dest)
  399. {
  400. graph_list_t m_graph_src = (graph_list_t) graph_src;
  401. graph_list_t m_graph_dest = (graph_list_t) graph_dest;
  402. linked_list_t list_src, list_dest;
  403. linked_list_iterator_t it_src, it_dest;
  404. int i, size;
  405. _ASSERT(graph_src, ==, NULL, NULL_POINTER,);
  406. _ASSERT(graph_dest, ==, NULL, NULL_POINTER,);
  407. _ASSERT(m_graph_src->size, != , m_graph_dest->size, INVALID_INPUT,);
  408. size = m_graph_src->size;
  409. for (i = 0; i < size; i++)
  410. {
  411. list_src = vector_get_key_at(m_graph_src->adjacency_list, i);
  412. it_src = linked_list_get_begin(list_src);
  413. list_dest = vector_get_key_at(m_graph_dest->adjacency_list, i);
  414. it_dest = linked_list_get_back(list_dest);
  415. while (it_src)
  416. {
  417. linked_list_iterator_set_key(it_dest, linked_list_iterator_get_key(
  418. it_src));
  419. it_src = linked_list_iterator_get_next(it_src);
  420. }
  421. }
  422. }
  423. static void *_store_linked_list_clone(void *key, void *context)
  424. {
  425. return linked_list_clone(key, NULL, NULL);
  426. }
  427. void *graph_list_store(void *graph_src)
  428. {
  429. graph_list_t m_graph = (graph_list_t) graph_src;
  430. graph_list_t m_clone;
  431. _ASSERT(graph_src, ==, NULL, NULL_POINTER, NULL);
  432. m_clone = (graph_list_t) _new(sizeof(struct _graph_list_t));
  433. m_clone->size = m_graph->size;
  434. m_clone->adjacency_list = vector_clone(m_graph->adjacency_list,
  435. _store_linked_list_clone, NULL);
  436. return m_clone;
  437. }
  438. void graph_list_debug(void *graph)
  439. {
  440. graph_list_t m_graph = (graph_list_t) graph;
  441. linked_list_t list;
  442. linked_list_iterator_t it;
  443. int i, n;
  444. _ASSERT(graph, ==, NULL, NULL_POINTER,);
  445. n = m_graph->size;
  446. for (i = 0; i < n; i++)
  447. {
  448. list = vector_get_key_at(m_graph->adjacency_list, i);
  449. it = linked_list_get_begin(list);
  450. while (1)
  451. {
  452. if (it == NULL)
  453. break;
  454. edge_debug(linked_list_iterator_get_key(it), NULL);
  455. it = linked_list_iterator_get_next(it);
  456. }
  457. }
  458. }
  459. graph_implementation_t graph_list_get_implementation()
  460. {
  461. static struct _graph_implementation_t _graph_adjacency_list_implementation;
  462. _graph_adjacency_list_implementation.new_g = graph_list_new;
  463. _graph_adjacency_list_implementation.delete_g = graph_list_delete;
  464. _graph_adjacency_list_implementation.resize = graph_list_resize;
  465. _graph_adjacency_list_implementation.add_edge = graph_list_add_edge;
  466. _graph_adjacency_list_implementation.remove_edge = graph_list_remove_edge;
  467. _graph_adjacency_list_implementation.get_edge = graph_list_get_edge;
  468. _graph_adjacency_list_implementation.first_vertex = graph_list_first_vertex;
  469. _graph_adjacency_list_implementation.delete_vertex_context
  470. = graph_list_delete_vertex_context;
  471. _graph_adjacency_list_implementation.next_vertex = graph_list_next_vertex;
  472. _graph_adjacency_list_implementation.first_edge = graph_list_first_edge;
  473. _graph_adjacency_list_implementation.delete_edge_context
  474. = graph_list_delete_edge_context;
  475. _graph_adjacency_list_implementation.next_edge = graph_list_next_edge;
  476. _graph_adjacency_list_implementation.iterate_edges
  477. = graph_list_iterate_edges;
  478. _graph_adjacency_list_implementation.transpose = graph_list_transpose;
  479. _graph_adjacency_list_implementation.vertex_degree
  480. = graph_list_vertex_degree;
  481. _graph_adjacency_list_implementation.vertex_in_degree
  482. = graph_list_vertex_in_degree;
  483. _graph_adjacency_list_implementation.vertex_out_degree
  484. = graph_list_vertex_out_degree;
  485. _graph_adjacency_list_implementation.dimension = graph_list_dimension;
  486. _graph_adjacency_list_implementation.delete_vertex_edges
  487. = graph_list_delete_vertex_edges;
  488. _graph_adjacency_list_implementation.load = graph_list_load;
  489. _graph_adjacency_list_implementation.store = graph_list_store;
  490. _graph_adjacency_list_implementation.debug = graph_list_debug;
  491. return &_graph_adjacency_list_implementation;
  492. }