| 10 | #include "../graph/entities/qg_edge.h" |
| 11 | |
| 12 | bool _DFS(QGNode *n, int level, bool close_cycle, int current_level, rax *visited, rax *used_edges, |
| 13 | QGEdge ***path) { |
| 14 | // As long as we've yet to reach required level and there are nodes to process. |
| 15 | if(current_level >= level) return true; |
| 16 | |
| 17 | // Mark n as visited, return if node already marked. |
| 18 | if(!raxInsert(visited, (unsigned char *)n->alias, strlen(n->alias), NULL, NULL)) { |
| 19 | // We've already processed n. |
| 20 | return false; |
| 21 | } |
| 22 | |
| 23 | // Expand node N by visiting all of its neighbors |
| 24 | bool not_seen; |
| 25 | for(uint i = 0; i < array_len(n->outgoing_edges); i++) { |
| 26 | QGEdge *e = n->outgoing_edges[i]; |
| 27 | not_seen = raxFind(visited, (unsigned char *)e->dest->alias, strlen(e->dest->alias)) == raxNotFound; |
| 28 | if(not_seen || close_cycle) { |
| 29 | if(!raxInsert(used_edges, (unsigned char *)e->alias, strlen(e->alias), NULL, NULL)) continue; |
| 30 | array_append(*path, e); |
| 31 | if(_DFS(e->dest, level, close_cycle, current_level + 1, visited, used_edges, path)) return true; |
| 32 | array_pop(*path); |
| 33 | raxRemove(used_edges, (unsigned char *)e->alias, strlen(e->alias), NULL); |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | for(uint i = 0; i < array_len(n->incoming_edges); i++) { |
| 38 | QGEdge *e = n->incoming_edges[i]; |
| 39 | not_seen = raxFind(visited, (unsigned char *)e->src->alias, strlen(e->src->alias)) == raxNotFound; |
| 40 | if(not_seen || close_cycle) { |
| 41 | if(!raxInsert(used_edges, (unsigned char *)e->alias, strlen(e->alias), NULL, NULL)) continue; |
| 42 | array_append(*path, e); |
| 43 | if(_DFS(e->src, level, close_cycle, current_level + 1, visited, used_edges, path)) return true; |
| 44 | array_pop(*path); |
| 45 | raxRemove(used_edges, (unsigned char *)e->alias, strlen(e->alias), NULL); |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | raxRemove(visited, (unsigned char *)n->alias, strlen(n->alias), NULL); |
| 50 | return false; |
| 51 | } |
| 52 | |
| 53 | // Returns a single path from S to a reachable node at distance level. |
| 54 | QGEdge **DFS(QGNode *s, int level, bool close_cycle) { |