To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
root / _FullBNT / BNT / graph / Old / .svn / text-base / dfs.m.svn-base @ 8:b5b38998ef3b
History | View | Annotate | Download (2.76 KB)
| 1 |
function [d, pre, post, height, cycle, pred] = dfs(adj_mat, start, directed) |
|---|---|
| 2 |
% DFS Perform a depth-first search of the graph starting from 'start'. |
| 3 |
% [d, pre, post, height, cycle, pred] = dfs(adj_mat, start, directed) |
| 4 |
% |
| 5 |
% d(i) is the time at which node i is first discovered. |
| 6 |
% pre is a listing of the nodes in the order in which they are first encountered (opened). |
| 7 |
% post is a listing of the nodes in the order in which they are last encountered (closed). |
| 8 |
% A node is last encountered once we have explored all of its neighbors. |
| 9 |
% If the graph is directed, i's neighbors are its children. |
| 10 |
% If the graph is a tree, preorder is parents before children, and |
| 11 |
% postorder is children before parents. |
| 12 |
% For a DAG, topological order = reverse(postorder). |
| 13 |
% height(i) is the height (distance) of node i from the start. |
| 14 |
% 'cycle' is true iff a (directed) cycle is found. |
| 15 |
% pred(i) is the parent of i in the dfs tree rooted at start. |
| 16 |
% See Cormen, Leiserson and Rivest, "An intro. to algorithms" 1994, p478. |
| 17 |
|
| 18 |
% We can detect undirected cycles by checking if we are about to visit a node n which we have |
| 19 |
% already visited. To detect *directed* cycles, we need to know if n has been closed or is still open. |
| 20 |
% For example (where arcs are directed down) |
| 21 |
% 1 2 |
| 22 |
% \ / |
| 23 |
% 3 |
| 24 |
% Assume we visit 1, 3 and then 2 in order. The fact that a child of 2 (namely, 3) has |
| 25 |
% already been visited is okay, because 3 has been closed. |
| 26 |
% The algorithms in Aho, Hopcroft and Ullman, and Sedgewick, do not detect directed cycles. |
| 27 |
|
| 28 |
n = length(adj_mat); |
| 29 |
|
| 30 |
global white gray black |
| 31 |
white = 0; gray = 1; black = 2; |
| 32 |
|
| 33 |
color = white*ones(1,n); |
| 34 |
d = zeros(1,n); |
| 35 |
height = zeros(1,n); |
| 36 |
pred = zeros(1,n); |
| 37 |
pre = []; |
| 38 |
post = []; |
| 39 |
cycle = 0; |
| 40 |
global count |
| 41 |
count = 0; |
| 42 |
h = 0; |
| 43 |
[d, pre, post, height, cycle, color, pred] = ... |
| 44 |
dfs2(adj_mat, start, directed, h, d, pre, post, height, cycle, color, pred); |
| 45 |
|
| 46 |
|
| 47 |
|
| 48 |
%%%%%%%%%% |
| 49 |
|
| 50 |
function [d, pre, post, height, cycle, color, pred] = ... |
| 51 |
dfs2(adj_mat, i, directed, h, d, pre, post, height, cycle, color, pred) |
| 52 |
|
| 53 |
global count |
| 54 |
global white gray black |
| 55 |
|
| 56 |
color(i) = gray; |
| 57 |
count = count + 1; |
| 58 |
d(i) = count; |
| 59 |
pre = [pre i]; |
| 60 |
height(i) = h; |
| 61 |
if directed |
| 62 |
ns = children(adj_mat, i); |
| 63 |
else |
| 64 |
ns = neighbors(adj_mat, i); |
| 65 |
end |
| 66 |
for j=1:length(ns) |
| 67 |
n=ns(j); |
| 68 |
if ~directed & n==pred(i) % don't go back up the edge you just came down |
| 69 |
% continue |
| 70 |
else |
| 71 |
if color(n) == gray % going back to a non-closed vertex via a new edge |
| 72 |
%fprintf(1, 'cycle from %d to %d\n', i, n); |
| 73 |
cycle = 1; |
| 74 |
end |
| 75 |
if color(n) == white % not visited n before |
| 76 |
pred(n)=i; |
| 77 |
[d, pre, post, height, cycle, color, pred] = ... |
| 78 |
dfs2(adj_mat, n, directed, h+1, d, pre, post, height, cycle, color, pred); |
| 79 |
end |
| 80 |
end |
| 81 |
end |
| 82 |
color(i) = black; |
| 83 |
post = [post i]; |
| 84 |
|