Returns a set of nodes reached at given level from S.
| 13 | |
| 14 | // Returns a set of nodes reached at given level from S. |
| 15 | QGNode **BFS(QGNode *s, int *level) { |
| 16 | void *seen; // Has node been visited? |
| 17 | int current_level = 0; // Tracks BFS level. |
| 18 | rax *visited = raxNew(); // Dictionary of visited nodes. |
| 19 | QGNode **next = array_new(QGNode *, 0); // Nodes to explore next. |
| 20 | QGNode **current = array_new(QGNode *, 1); // Nodes currently explored. |
| 21 | |
| 22 | array_append(current, s); |
| 23 | |
| 24 | // As long as we've yet to reach required level and there are nodes to process. |
| 25 | while(current_level < *level && array_len(current)) { |
| 26 | // As long as there are nodes in the frontier. |
| 27 | for(int i = 0; i < array_len(current); i++) { |
| 28 | QGNode *n = current[i]; |
| 29 | |
| 30 | // Have we already processed n? |
| 31 | seen = raxFind(visited, (unsigned char *)n->alias, strlen(n->alias)); |
| 32 | if(seen != raxNotFound) continue; |
| 33 | |
| 34 | // Expand node N by visiting all of its neighbors |
| 35 | for(int j = 0; j < array_len(n->outgoing_edges); j++) { |
| 36 | QGEdge *e = n->outgoing_edges[j]; |
| 37 | seen = raxFind(visited, (unsigned char *)e->dest->alias, strlen(e->dest->alias)); |
| 38 | if(seen == raxNotFound) { |
| 39 | array_append(next, e->dest); |
| 40 | } |
| 41 | } |
| 42 | for(int j = 0; j < array_len(n->incoming_edges); j++) { |
| 43 | QGEdge *e = n->incoming_edges[j]; |
| 44 | seen = raxFind(visited, (unsigned char *)e->src->alias, strlen(e->src->alias)); |
| 45 | if(seen == raxNotFound) { |
| 46 | array_append(next, e->src); |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | // Mark n as visited. |
| 51 | raxInsert(visited, (unsigned char *)n->alias, strlen(n->alias), NULL, NULL); |
| 52 | } |
| 53 | |
| 54 | /* No way to progress and we're interested in the lowest level leafs |
| 55 | * do not clear current queue. */ |
| 56 | if(array_len(next) == 0 && *level == BFS_LOWEST_LEVEL) { |
| 57 | *level = current_level; |
| 58 | break; |
| 59 | } |
| 60 | |
| 61 | // Queue consumed, swap queues. |
| 62 | array_clear(current); |
| 63 | QGNode **tmp = current; |
| 64 | current = next; |
| 65 | next = tmp; |
| 66 | current_level++; |
| 67 | } |
| 68 | |
| 69 | raxFree(visited); |
| 70 | array_free(next); |
| 71 | return current; |
| 72 | } |