span-template.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. /* LIBDGL -- a Directed Graph Library implementation
  2. * Copyright (C) 2002 Roberto Micarelli
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  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. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. /*
  19. * best view with tabstop=4
  20. */
  21. /*
  22. * Build the depth-first spanning tree of 'pgraphIn' into 'pgraphOut'
  23. * - pgraphOut must have been previously initialized by the caller and is returned in TREE state
  24. * - I prefer using a iterative approach with a stack for 'waiting edges' instead of recursion: it's
  25. * cheaper to stack 8 bytes for each edge than the whole function stack
  26. * - The visited network is passed by the caller because this function can be used for two purposes:
  27. * 1. generate a single spanning tree (dglDepthSpanning)
  28. * 2. part of a loop for generating connected-components of the graph (dglDepthComponents)
  29. */
  30. int DGL_SPAN_DEPTHFIRST_SPANNING_FUNC(dglGraph_s * pgraphIn,
  31. dglGraph_s * pgraphOut,
  32. dglInt32_t nVertex,
  33. void *pvVisited,
  34. dglSpanClip_fn fnClip, void *pvClipArg)
  35. {
  36. struct _stackItem
  37. {
  38. dglInt32_t *pnHead;
  39. dglInt32_t *pnEdge;
  40. int iWay;
  41. };
  42. struct _stackItem stackItem;
  43. struct _stackItem *pStackItem;
  44. dglInt32_t *pHead;
  45. dglInt32_t *pTail;
  46. dglInt32_t *pEdgeset;
  47. dglInt32_t *pEdge;
  48. long istack = 0;
  49. unsigned char *pstack = NULL;
  50. int nret;
  51. dglSpanClipInput_s clipInput;
  52. dglTreeNode_s findVisited;
  53. dglEdgesetTraverser_s laT;
  54. if ((pHead = dglGetNode(pgraphIn, nVertex)) == NULL) {
  55. pgraphIn->iErrno = DGL_ERR_HeadNodeNotFound;
  56. goto dfs_error;
  57. }
  58. /*
  59. * the simplest case is when vertex node is alone or has no outgoing edges, the result
  60. * of the spanning is a graph having only one node
  61. */
  62. if (DGL_NODE_STATUS(pHead) & DGL_NS_ALONE ||
  63. (!(DGL_NODE_STATUS(pHead) & DGL_NS_HEAD) &&
  64. DGL_NODE_STATUS(pHead) & DGL_NS_TAIL)) {
  65. nret =
  66. DGL_ADD_NODE_FUNC(pgraphOut, DGL_NODE_ID(pHead),
  67. DGL_NODE_ATTR_PTR(pHead), 0);
  68. if (nret < 0) {
  69. goto dfs_error;
  70. }
  71. return 0;
  72. }
  73. if ((DGL_NODE_STATUS(pHead) & DGL_NS_HEAD) || pgraphIn->Version == 3) {
  74. pEdgeset = _DGL_OUTEDGESET(pgraphIn, pHead);
  75. if (DGL_EDGESET_T_INITIALIZE_FUNC(pgraphIn, &laT, pEdgeset) < 0) {
  76. goto dfs_error;
  77. }
  78. for (pEdge = DGL_EDGESET_T_FIRST_FUNC(&laT);
  79. pEdge; pEdge = DGL_EDGESET_T_NEXT_FUNC(&laT)
  80. ) {
  81. stackItem.pnHead = pHead;
  82. stackItem.pnEdge = pEdge;
  83. stackItem.iWay = 0;
  84. if ((pstack =
  85. dgl_mempush(pstack, &istack, sizeof(stackItem),
  86. &stackItem)) == NULL) {
  87. pgraphIn->iErrno = DGL_ERR_MemoryExhausted;
  88. goto dfs_error;
  89. }
  90. }
  91. DGL_EDGESET_T_RELEASE_FUNC(&laT);
  92. if (pgraphIn->Version == 3) {
  93. pEdgeset = _DGL_INEDGESET(pgraphIn, pHead);
  94. if (DGL_EDGESET_T_INITIALIZE_FUNC(pgraphIn, &laT, pEdgeset) < 0) {
  95. goto dfs_error;
  96. }
  97. for (pEdge = DGL_EDGESET_T_FIRST_FUNC(&laT);
  98. pEdge; pEdge = DGL_EDGESET_T_NEXT_FUNC(&laT)
  99. ) {
  100. if (DGL_EDGE_STATUS(pEdge) & DGL_ES_DIRECTED)
  101. continue;
  102. stackItem.pnHead = pHead;
  103. stackItem.pnEdge = pEdge;
  104. stackItem.iWay = 1;
  105. if ((pstack =
  106. dgl_mempush(pstack, &istack, sizeof(stackItem),
  107. &stackItem)) == NULL) {
  108. pgraphIn->iErrno = DGL_ERR_MemoryExhausted;
  109. goto dfs_error;
  110. }
  111. }
  112. DGL_EDGESET_T_RELEASE_FUNC(&laT);
  113. }
  114. if (dglTreeNodeAdd(pvVisited, DGL_NODE_ID(pHead)) == NULL) {
  115. pgraphIn->iErrno = DGL_ERR_MemoryExhausted;
  116. goto dfs_error;
  117. }
  118. }
  119. while ((pStackItem =
  120. (struct _stackItem *)dgl_mempop(pstack, &istack,
  121. sizeof(stackItem))) != NULL) {
  122. pHead = pStackItem->pnHead;
  123. pEdge = pStackItem->pnEdge;
  124. if (pStackItem->iWay == 0)
  125. pTail = _DGL_EDGE_TAILNODE(pgraphIn, pEdge);
  126. else
  127. pTail = _DGL_EDGE_HEADNODE(pgraphIn, pEdge);
  128. findVisited.nKey = DGL_NODE_ID(pTail);
  129. if (avl_find(pvVisited, &findVisited)) { /* already visited */
  130. continue;
  131. }
  132. if (fnClip) {
  133. clipInput.pnNodeFrom = pHead;
  134. clipInput.pnEdge = pEdge;
  135. clipInput.pnNodeTo = pTail;
  136. if (fnClip(pgraphIn, pgraphOut, &clipInput, NULL, pvClipArg))
  137. continue;
  138. }
  139. if (dglTreeNodeAdd(pvVisited, DGL_NODE_ID(pTail)) == NULL) {
  140. pgraphIn->iErrno = DGL_ERR_MemoryExhausted;
  141. goto dfs_error;
  142. }
  143. /* add this edge */
  144. nret = DGL_ADD_EDGE_FUNC(pgraphOut,
  145. DGL_NODE_ID(pHead),
  146. DGL_NODE_ID(pTail),
  147. DGL_EDGE_COST(pEdge),
  148. DGL_EDGE_ID(pEdge),
  149. DGL_NODE_ATTR_PTR(pHead),
  150. DGL_NODE_ATTR_PTR(pTail),
  151. DGL_EDGE_ATTR_PTR(pEdge), 0);
  152. if (nret < 0) {
  153. goto dfs_error;
  154. }
  155. if ((DGL_NODE_STATUS(pHead) & DGL_NS_HEAD) || pgraphIn->Version == 3) {
  156. pEdgeset = _DGL_OUTEDGESET(pgraphIn, pTail);
  157. if (DGL_EDGESET_T_INITIALIZE_FUNC(pgraphIn, &laT, pEdgeset) < 0) {
  158. goto dfs_error;
  159. }
  160. for (pEdge = DGL_EDGESET_T_FIRST_FUNC(&laT);
  161. pEdge; pEdge = DGL_EDGESET_T_NEXT_FUNC(&laT)
  162. ) {
  163. stackItem.pnHead = pTail;
  164. stackItem.pnEdge = pEdge;
  165. stackItem.iWay = 0;
  166. if ((pstack =
  167. dgl_mempush(pstack, &istack, sizeof(stackItem),
  168. &stackItem)) == NULL) {
  169. pgraphIn->iErrno = DGL_ERR_MemoryExhausted;
  170. goto dfs_error;
  171. }
  172. }
  173. DGL_EDGESET_T_RELEASE_FUNC(&laT);
  174. if (pgraphIn->Version == 3) {
  175. pEdgeset = _DGL_INEDGESET(pgraphIn, pTail);
  176. if (DGL_EDGESET_T_INITIALIZE_FUNC(pgraphIn, &laT, pEdgeset) <
  177. 0) {
  178. goto dfs_error;
  179. }
  180. for (pEdge = DGL_EDGESET_T_FIRST_FUNC(&laT);
  181. pEdge; pEdge = DGL_EDGESET_T_NEXT_FUNC(&laT)
  182. ) {
  183. if (DGL_EDGE_STATUS(pEdge) & DGL_ES_DIRECTED)
  184. continue;
  185. stackItem.pnHead = pTail;
  186. stackItem.pnEdge = pEdge;
  187. stackItem.iWay = 1;
  188. if ((pstack =
  189. dgl_mempush(pstack, &istack, sizeof(stackItem),
  190. &stackItem)) == NULL) {
  191. pgraphIn->iErrno = DGL_ERR_MemoryExhausted;
  192. goto dfs_error;
  193. }
  194. }
  195. DGL_EDGESET_T_RELEASE_FUNC(&laT);
  196. }
  197. }
  198. }
  199. if (pstack)
  200. free(pstack);
  201. return 0;
  202. dfs_error:
  203. if (pstack)
  204. free(pstack);
  205. return -pgraphIn->iErrno;
  206. }
  207. /*
  208. * Use a edge prioritized, tree growing scheme (aka Prim algorithm) in order to
  209. * be appliable to both undirected graphs (minimum spanning tree - MST) and
  210. * digraphs (minimum arborescense tree - MAT)
  211. * The vertex argument is ignored in MST (when algorithm is applied to a
  212. * version 3 undirected graph).
  213. */
  214. int DGL_SPAN_MINIMUM_SPANNING_FUNC(dglGraph_s * pgraphIn,
  215. dglGraph_s * pgraphOut,
  216. dglInt32_t nVertex,
  217. dglSpanClip_fn fnClip, void *pvClipArg)
  218. {
  219. dglInt32_t *pHead, *pTail, *pEdgeset, *pEdge;
  220. dglHeap_s FrontEdgeHeap;
  221. dglHeapData_u HeapData;
  222. dglHeapNode_s HeapItem;
  223. dglTreeNode_s *pPredistItem, findItem;
  224. dglEdgesetTraverser_s laT;
  225. int nret;
  226. dglHeapInit(&FrontEdgeHeap);
  227. if (pgraphIn->Version == 3) { /* undirected: pick up the first node */
  228. dglNodeTraverser_s pT;
  229. DGL_NODE_T_INITIALIZE_FUNC(pgraphIn, &pT);
  230. pHead = DGL_NODE_T_FIRST_FUNC(&pT);
  231. DGL_NODE_T_RELEASE_FUNC(&pT);
  232. }
  233. else { /* directed: pick up the arborescense origin */
  234. pHead = DGL_GET_NODE_FUNC(pgraphIn, nVertex);
  235. }
  236. if (pHead == NULL) {
  237. pgraphIn->iErrno = DGL_ERR_HeadNodeNotFound;
  238. goto mst_error;
  239. }
  240. if (DGL_NODE_STATUS(pHead) & DGL_NS_HEAD ||
  241. DGL_NODE_STATUS(pHead) & DGL_NS_ALONE) {
  242. if ((DGL_NODE_STATUS(pHead) & DGL_NS_HEAD) ||
  243. (DGL_NODE_STATUS(pHead) & DGL_NS_ALONE) ||
  244. pgraphIn->Version == 3) {
  245. if (DGL_ADD_NODE_FUNC
  246. (pgraphOut, DGL_NODE_ID(pHead), DGL_NODE_ATTR_PTR(pHead),
  247. 0) < 0) {
  248. goto mst_error;
  249. }
  250. if (DGL_NODE_STATUS(pHead) & DGL_NS_ALONE) {
  251. dglHeapFree(&FrontEdgeHeap, NULL);
  252. return 0;
  253. }
  254. pEdgeset = _DGL_OUTEDGESET(pgraphIn, pHead);
  255. if (DGL_EDGESET_T_INITIALIZE_FUNC(pgraphIn, &laT, pEdgeset) < 0) {
  256. goto mst_error;
  257. }
  258. for (pEdge = DGL_EDGESET_T_FIRST_FUNC(&laT);
  259. pEdge; pEdge = DGL_EDGESET_T_NEXT_FUNC(&laT)
  260. ) {
  261. HeapData.pv = pEdge;
  262. if (dglHeapInsertMin
  263. (&FrontEdgeHeap, DGL_EDGE_COST(pEdge), 0, HeapData) < 0) {
  264. pgraphIn->iErrno = DGL_ERR_HeapError;
  265. goto mst_error;
  266. }
  267. }
  268. DGL_EDGESET_T_RELEASE_FUNC(&laT);
  269. if (pgraphIn->Version == 3) {
  270. pEdgeset = _DGL_INEDGESET(pgraphIn, pHead);
  271. if (DGL_EDGESET_T_INITIALIZE_FUNC(pgraphIn, &laT, pEdgeset) <
  272. 0) {
  273. goto mst_error;
  274. }
  275. for (pEdge = DGL_EDGESET_T_FIRST_FUNC(&laT);
  276. pEdge; pEdge = DGL_EDGESET_T_NEXT_FUNC(&laT)
  277. ) {
  278. if (DGL_EDGE_STATUS(pEdge) & DGL_ES_DIRECTED)
  279. continue;
  280. HeapData.pv = pEdge;
  281. if (dglHeapInsertMin
  282. (&FrontEdgeHeap, DGL_EDGE_COST(pEdge), 1,
  283. HeapData) < 0) {
  284. pgraphIn->iErrno = DGL_ERR_HeapError;
  285. goto mst_error;
  286. }
  287. }
  288. DGL_EDGESET_T_RELEASE_FUNC(&laT);
  289. }
  290. }
  291. }
  292. else {
  293. pgraphIn->iErrno = DGL_ERR_BadEdge;
  294. goto mst_error;
  295. }
  296. while (dglHeapExtractMin(&FrontEdgeHeap, &HeapItem) == 1) {
  297. pEdge = HeapItem.value.pv;
  298. if (HeapItem.flags == 0) {
  299. if ((pHead = _DGL_EDGE_HEADNODE(pgraphIn, pEdge)) == NULL) {
  300. pgraphIn->iErrno = DGL_ERR_UnexpectedNullPointer;
  301. goto mst_error;
  302. }
  303. if ((pTail = _DGL_EDGE_TAILNODE(pgraphIn, pEdge)) == NULL) {
  304. pgraphIn->iErrno = DGL_ERR_UnexpectedNullPointer;
  305. goto mst_error;
  306. }
  307. }
  308. else if (pgraphIn->Version == 3) {
  309. if ((pTail = _DGL_EDGE_HEADNODE(pgraphIn, pEdge)) == NULL) {
  310. pgraphIn->iErrno = DGL_ERR_UnexpectedNullPointer;
  311. goto mst_error;
  312. }
  313. if ((pHead = _DGL_EDGE_TAILNODE(pgraphIn, pEdge)) == NULL) {
  314. pgraphIn->iErrno = DGL_ERR_UnexpectedNullPointer;
  315. goto mst_error;
  316. }
  317. }
  318. else
  319. continue;
  320. findItem.nKey = DGL_NODE_ID(pTail);
  321. if ((pPredistItem =
  322. avl_find(pgraphOut->pNodeTree, &findItem)) != NULL) {
  323. continue;
  324. }
  325. nret = DGL_ADD_EDGE_FUNC(pgraphOut,
  326. DGL_NODE_ID(pHead),
  327. DGL_NODE_ID(pTail),
  328. DGL_EDGE_COST(pEdge),
  329. DGL_EDGE_ID(pEdge),
  330. DGL_NODE_ATTR_PTR(pHead),
  331. DGL_NODE_ATTR_PTR(pTail),
  332. DGL_EDGE_ATTR_PTR(pEdge), 0);
  333. if (nret < 0) {
  334. goto mst_error;
  335. }
  336. pHead = pTail;
  337. if ((DGL_NODE_STATUS(pHead) & DGL_NS_HEAD) || pgraphIn->Version == 3) {
  338. pEdgeset = _DGL_OUTEDGESET(pgraphIn, pHead);
  339. if (DGL_EDGESET_T_INITIALIZE_FUNC(pgraphIn, &laT, pEdgeset) < 0) {
  340. goto mst_error;
  341. }
  342. for (pEdge = DGL_EDGESET_T_FIRST_FUNC(&laT);
  343. pEdge; pEdge = DGL_EDGESET_T_NEXT_FUNC(&laT)
  344. ) {
  345. HeapData.pv = pEdge;
  346. if (dglHeapInsertMin
  347. (&FrontEdgeHeap, DGL_EDGE_COST(pEdge), 0, HeapData) < 0) {
  348. pgraphIn->iErrno = DGL_ERR_HeapError;
  349. goto mst_error;
  350. }
  351. }
  352. if (pgraphIn->Version == 3) {
  353. DGL_EDGESET_T_RELEASE_FUNC(&laT);
  354. pEdgeset = _DGL_OUTEDGESET(pgraphIn, pHead);
  355. if (DGL_EDGESET_T_INITIALIZE_FUNC(pgraphIn, &laT, pEdgeset) <
  356. 0) {
  357. goto mst_error;
  358. }
  359. for (pEdge = DGL_EDGESET_T_FIRST_FUNC(&laT);
  360. pEdge; pEdge = DGL_EDGESET_T_NEXT_FUNC(&laT)
  361. ) {
  362. if (DGL_EDGE_STATUS(pEdge) & DGL_ES_DIRECTED)
  363. continue;
  364. HeapData.pv = pEdge;
  365. if (dglHeapInsertMin
  366. (&FrontEdgeHeap, DGL_EDGE_COST(pEdge), 1,
  367. HeapData) < 0) {
  368. pgraphIn->iErrno = DGL_ERR_HeapError;
  369. goto mst_error;
  370. }
  371. }
  372. DGL_EDGESET_T_RELEASE_FUNC(&laT);
  373. }
  374. }
  375. }
  376. dglHeapFree(&FrontEdgeHeap, NULL);
  377. return 0;
  378. mst_error:
  379. dglHeapFree(&FrontEdgeHeap, NULL);
  380. return -pgraphIn->iErrno;
  381. }