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

org.psjava.algo.graph.LowestCommonAncestorAlgorithm Maven / Gradle / Ivy

The newest version!
package org.psjava.algo.graph;

import java.util.Comparator;

import org.psjava.algo.graph.dfs.DFSVisitorBase;
import org.psjava.algo.graph.dfs.SingleSourceDFS;
import org.psjava.algo.sequence.rmq.RangeMinimumQuerySession;
import org.psjava.algo.sequence.rmq.RangeMinimumQuery;
import org.psjava.ds.array.DynamicArray;
import org.psjava.ds.array.LastInArray;
import org.psjava.ds.graph.DirectedEdge;
import org.psjava.ds.graph.RootedTree;
import org.psjava.ds.map.MutableMap;
import org.psjava.ds.map.MutableMapFactory;
import org.psjava.util.VisitorStopper;

public class LowestCommonAncestorAlgorithm {

	private MutableMapFactory mapFactory;
	private RangeMinimumQuery rmq;

	public LowestCommonAncestorAlgorithm(RangeMinimumQuery rmq, MutableMapFactory mapFactory) {
		this.rmq = rmq;
		this.mapFactory = mapFactory;
	}

	private static class VertexAndDepth {
		final V vertex;
		final int depth;
		VertexAndDepth(V v, int d) {
			this.vertex = v;
			this.depth = d;
		}
	}

	public > LowestCommonAncestorQuerySession calc(RootedTree tree) {
		final MutableMap discoverIndex = mapFactory.create();
		final DynamicArray> history = DynamicArray.create(); // stores vertex and depth

		SingleSourceDFS.traverse(tree.graph, tree.root, new DFSVisitorBase() {
			@Override
			public void onDiscovered(V vertex, int depth, VisitorStopper stopper) {
				discoverIndex.add(vertex, history.size());
				history.addToLast(new VertexAndDepth(vertex, depth));
			}

			@Override
			public void onWalkUp(E downedEdge) {
				int lastDepth = LastInArray.getLast(history).depth;
				history.addToLast(new VertexAndDepth(downedEdge.from(), lastDepth - 1));
			}
		});

		final RangeMinimumQuerySession rmqSession = rmq.preprocess(history, new Comparator>() {
			@Override
			public int compare(VertexAndDepth o1, VertexAndDepth o2) {
				return o1.depth - o2.depth;
			}
		});

		return new LowestCommonAncestorQuerySession() {
			@Override
			public V query(V v1, V v2) {
				int i1 = discoverIndex.get(v1);
				int i2 = discoverIndex.get(v2);
				return history.get(rmqSession.getIndex(Math.min(i1, i2), Math.max(i1, i2) + 1)).vertex;
			}
		};
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy