DFS in virtual graph with cycles

68 views Asked by At

Using a function that generates a list of "adjacent" values from an input value, i.e.

Function<Object, List<?>> adjacent;

one can "traverse" any "acyclic" collection of values as a virtual graph using, for example, Depth-First Search (DFS) in a non-recursive implementation.

public static void dfs(Object start, Function<Object, List<?>> adjacent) {
  Object current;
  List<?> children;
  ListIterator<?> iterator;
  Stack<Object> stack = new Stack<>();
  stack.push(start);
  while (!stack.isEmpty()) {
    current = stack.pop();
    System.out.println(current.toString()); // Value "visited" 
    children = adjacent.apply(current);
    if (children == null) continue;
    iterator = children.listIterator(children.size());
    while (iterator.hasPrevious()) {
      stack.push(iterator.previous());
    }
  }
}

However, if there are any "cycles" in the collection (i.e., if any "child" value has as its own child a previously "visited" member of the collection, as determined by the adjacent function), the dfs() method above results in an infinite loop, since it does not mark already "visited" values as such.

Assuming that there is no way to modify the adjacent function, nor to trust the (whatever) implementation of equals()/hashCode() for the supplied values, each of which may be a new object, can there be any way of denoting "visited" values? Wrapping them in a new object with a boolean to mark "visited" values won't work, because the adjacent method will output generic values, not knowing whether they have been visited or not.

A simple adjacent method to test is, for example, map::get, with a map like

Map<Integer, List<Integer>> map = new LinkedHashMap<>();
map.put(0, Arrays.asList(1, 2));
map.put(1, Arrays.asList(3, 4));
map.put(3, Arrays.asList(1, 5));

Calling

dfs(0, map::get);

results in an infinite loop.

0

There are 0 answers