acyclic.c 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. /*
  11. * Break cycles in a directed graph by depth-first search.
  12. */
  13. #include <dotgen/dot.h>
  14. #include <stdbool.h>
  15. #include <stddef.h>
  16. void reverse_edge(edge_t * e)
  17. {
  18. edge_t *f;
  19. delete_fast_edge(e);
  20. if ((f = find_fast_edge(aghead(e), agtail(e))))
  21. merge_oneway(e, f);
  22. else
  23. virtual_edge(aghead(e), agtail(e), e);
  24. }
  25. static void
  26. dfs(node_t * n)
  27. {
  28. int i;
  29. edge_t *e;
  30. node_t *w;
  31. if (ND_mark(n))
  32. return;
  33. ND_mark(n) = true;
  34. ND_onstack(n) = true;
  35. for (i = 0; (e = ND_out(n).list[i]); i++) {
  36. w = aghead(e);
  37. if (ND_onstack(w)) {
  38. reverse_edge(e);
  39. i--;
  40. } else {
  41. if (!ND_mark(w))
  42. dfs(w);
  43. }
  44. }
  45. ND_onstack(n) = false;
  46. }
  47. void acyclic(graph_t * g)
  48. {
  49. node_t *n;
  50. for (size_t c = 0; c < GD_comp(g).size; c++) {
  51. GD_nlist(g) = GD_comp(g).list[c];
  52. for (n = GD_nlist(g); n; n = ND_next(n))
  53. ND_mark(n) = false;
  54. for (n = GD_nlist(g); n; n = ND_next(n))
  55. dfs(n);
  56. }
  57. }