All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cdc.graphs.core.GraphTraverser Maven / Gradle / Ivy

There is a newer version: 0.71.2
Show newest version
package cdc.graphs.core;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import cdc.graphs.EdgeDirection;
import cdc.graphs.EdgeTip;
import cdc.graphs.GraphAdapter;
import cdc.graphs.TraversalMethod;
import cdc.graphs.TraversalOrder;
import cdc.util.function.Evaluator;
import cdc.util.function.Visitor;
import cdc.util.lang.Checks;

/**
 * Class used to visit a graph.
 * 

* It is possible to choose: *

    *
  • The traversal method: breadth first or depth first. *
  • The traversal order: pre or post. *
  • The traversal direction: ingoing or outgoing. *
* * @author Damien Carbonne * * @param Node class * @param Edge class */ public class GraphTraverser extends GraphBase { static final Logger LOGGER = LogManager.getLogger(GraphTraverser.class); private static final String DIRECTION = "direction"; private static final String METHOD = "method"; private static final String NODE = "node"; private static final String ORDER = "order"; private static final String VISITOR = "visitor"; public GraphTraverser(GraphAdapter adapter) { super(adapter); } /** * Most generic traversal function. * * @param node The initial node. Must not be null. * @param method The traversal method. Must not be null. * @param order The traversal order. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. * @param evaluator An optional evaluator used to control traversal * termination. */ public void traverse(N node, TraversalMethod method, TraversalOrder order, EdgeDirection direction, Visitor visitor, Evaluator evaluator) { Checks.isNotNull(node, NODE); Checks.isNotNull(method, METHOD); Checks.isNotNull(order, ORDER); Checks.isNotNull(direction, DIRECTION); Checks.isNotNull(visitor, VISITOR); if (method == TraversalMethod.BREADTH_FIRST) { traverseBreadthFirst(node, order, direction, visitor, evaluator); } else { traverseDepthFirst(node, order, direction, visitor, evaluator); } } /** * Generic traversal, without evaluator. * * @param node The initial node. Must not be null. * @param method The traversal method. Must not be null. * @param order The traversal order. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. */ public void traverse(N node, TraversalMethod method, TraversalOrder order, EdgeDirection direction, Visitor visitor) { traverse(node, method, order, direction, visitor, null); } /** * Depth first traversal. * * @param node The initial node. Must not be null. * @param order The traversal order. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. * @param evaluator An optional evaluator used to control traversal * termination. */ public void traverseDepthFirst(N node, TraversalOrder order, EdgeDirection direction, Visitor visitor, Evaluator evaluator) { Checks.isNotNull(node, NODE); Checks.isNotNull(order, ORDER); Checks.isNotNull(direction, DIRECTION); Checks.isNotNull(visitor, VISITOR); final DepthFirstTraverser traverser = new DepthFirstTraverser(direction); if (order == TraversalOrder.POST_ORDER) { traverser.traversePost(node, visitor, evaluator); } else { traverser.traversePre(node, visitor, evaluator); } } /** * Depth first traversal without evaluator. * * @param node The initial node. Must not be null. * @param order The traversal order. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. */ public void traverseDepthFirst(N node, TraversalOrder order, EdgeDirection direction, Visitor visitor) { traverseDepthFirst(node, order, direction, visitor, null); } /** * Depth first pre order traversal. * * @param node The initial node. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. * @param evaluator An optional evaluator used to control traversal * termination. */ public void traverseDepthFirstPre(N node, EdgeDirection direction, Visitor visitor, Evaluator evaluator) { Checks.isNotNull(node, NODE); Checks.isNotNull(direction, DIRECTION); Checks.isNotNull(visitor, VISITOR); final DepthFirstTraverser traverser = new DepthFirstTraverser(direction); traverser.traversePre(node, visitor, evaluator); } /** * Depth first pre order traversal without evaluator. * * @param node The initial node. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. */ public void traverseDepthFirstPre(N node, EdgeDirection direction, Visitor visitor) { traverseDepthFirstPre(node, direction, visitor, null); } /** * Depth first post order traversal. * * @param node The initial node. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. * @param evaluator An optional evaluator used to control traversal * termination. */ public void traverseDepthFirstPost(N node, EdgeDirection direction, Visitor visitor, Evaluator evaluator) { Checks.isNotNull(node, NODE); Checks.isNotNull(direction, DIRECTION); Checks.isNotNull(visitor, VISITOR); final DepthFirstTraverser traverser = new DepthFirstTraverser(direction); traverser.traversePost(node, visitor, evaluator); } /** * Depth first post order traversal without evaluator. * * @param node The initial node. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. */ public void traverseDepthFirstPost(N node, EdgeDirection direction, Visitor visitor) { traverseDepthFirstPost(node, direction, visitor, null); } /** * Breadth first traversal. * * @param node The initial node. Must not be null. * @param order The traversal order. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. * @param evaluator An optional evaluator used to control traversal * termination. */ public void traverseBreadthFirst(N node, TraversalOrder order, EdgeDirection direction, Visitor visitor, Evaluator evaluator) { Checks.isNotNull(node, NODE); Checks.isNotNull(order, ORDER); Checks.isNotNull(direction, DIRECTION); Checks.isNotNull(visitor, VISITOR); final BreadthFirstTraverser traverser = new BreadthFirstTraverser(direction); if (order == TraversalOrder.POST_ORDER) { traverser.traversePost(node, visitor, evaluator); } else { traverser.traversePre(node, visitor, evaluator); } } /** * Breadth first traversal without evaluator. * * @param node The initial node. Must not be null. * @param order The traversal order. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. */ public void traverseBreadthFirst(N node, TraversalOrder order, EdgeDirection direction, Visitor visitor) { traverseBreadthFirst(node, order, direction, visitor, null); } /** * Breadth first pre order traversal. * * @param node The initial node. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. * @param evaluator An optional evaluator used to control traversal * termination. */ public void traverseBreadthFirstPre(N node, EdgeDirection direction, Visitor visitor, Evaluator evaluator) { Checks.isNotNull(node, NODE); Checks.isNotNull(direction, DIRECTION); Checks.isNotNull(visitor, VISITOR); final BreadthFirstTraverser traverser = new BreadthFirstTraverser(direction); traverser.traversePre(node, visitor, evaluator); } /** * Breadth first pre order traversal without evaluator. * * @param node The initial node. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. */ public void traverseBreadthFirstPre(N node, EdgeDirection direction, Visitor visitor) { traverseBreadthFirstPre(node, direction, visitor, null); } /** * Breadth first post order traversal. * * @param node The initial node. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. * @param evaluator An optional evaluator used to control traversal * termination. */ public void traverseBreadthFirstPost(N node, EdgeDirection direction, Visitor visitor, Evaluator evaluator) { Checks.isNotNull(node, NODE); Checks.isNotNull(direction, DIRECTION); Checks.isNotNull(visitor, VISITOR); final BreadthFirstTraverser traverser = new BreadthFirstTraverser(direction); traverser.traversePost(node, visitor, evaluator); } /** * Breadth first post order traversal without evaluator. * * @param node The initial node. Must not be null. * @param direction The edge direction to follow for traversal. Must not be null. * @param visitor Visitor that will be invoked for each visited node. Must not be null. */ public void traverseBreadthFirstPost(N node, EdgeDirection direction, Visitor visitor) { traverseBreadthFirstPost(node, direction, visitor, null); } /** * Depth first traversal class. * * @author Damien Carbonne * */ private class DepthFirstTraverser { private final Set visited = new HashSet<>(); private final EdgeDirection direction; private final EdgeTip tip; public DepthFirstTraverser(EdgeDirection direction) { this.direction = direction; this.tip = direction == EdgeDirection.INGOING ? EdgeTip.SOURCE : EdgeTip.TARGET; } void traversePre(N node, Visitor visitor, Evaluator evaluator) { visitor.visit(node); if (Evaluator.continueTraversal(evaluator, node)) { visited.add(node); for (final E edge : adapter.getEdges(node, direction)) { final N succ = adapter.getTip(edge, tip); if (!visited.contains(succ)) { traversePre(succ, visitor, evaluator); } } } } void traversePost(N node, Visitor visitor, Evaluator evaluator) { if (Evaluator.continueTraversal(evaluator, node)) { visited.add(node); for (final E edge : adapter.getEdges(node, direction)) { final N succ = adapter.getTip(edge, tip); if (!visited.contains(succ)) { traversePost(succ, visitor, evaluator); } } } visitor.visit(node); } } /** * Breadth first traversal class. * * @author Damien Carbonne * */ private class BreadthFirstTraverser { private final EdgeDirection direction; private final EdgeTip tip; public BreadthFirstTraverser(EdgeDirection direction) { this.direction = direction; this.tip = direction == EdgeDirection.INGOING ? EdgeTip.SOURCE : EdgeTip.TARGET; } void traversePre(N from, Visitor visitor, Evaluator evaluator) { final Deque q = new ArrayDeque<>(); final Set visited = new HashSet<>(); q.addLast(from); visited.add(from); while (!q.isEmpty()) { final N node = q.pollFirst(); visitor.visit(node); if (Evaluator.continueTraversal(evaluator, node)) { for (final E e : adapter.getEdges(node, direction)) { final N y = adapter.getTip(e, tip); if (!visited.contains(y)) { visited.add(y); q.addLast(y); } } } } } void traversePost(N from, Visitor visitor, Evaluator evaluator) { final List visited = new ArrayList<>(); traversePre(from, visited::add, evaluator); for (int index = visited.size() - 1; index >= 0; index--) { final N node = visited.get(index); visitor.visit(node); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy