001 /* 002 * Copyright 2010-2015 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.jetbrains.kotlin.utils; 018 019 import kotlin.jvm.KotlinSignature; 020 import org.jetbrains.annotations.NotNull; 021 022 import java.util.*; 023 024 public class DFS { 025 public static <N, R> R dfs(@NotNull Collection<N> nodes, @NotNull Neighbors<N> neighbors, @NotNull Visited<N> visited, @NotNull NodeHandler<N, R> handler) { 026 for (N node : nodes) { 027 doDfs(node, neighbors, visited, handler); 028 } 029 return handler.result(); 030 } 031 032 public static <N, R> R dfs( 033 @NotNull Collection<N> nodes, 034 @NotNull Neighbors<N> neighbors, 035 @NotNull NodeHandler<N, R> handler 036 ) { 037 return dfs(nodes, neighbors, new VisitedWithSet<N>(), handler); 038 } 039 040 public static <N, R> R dfsFromNode(@NotNull N node, @NotNull Neighbors<N> neighbors, @NotNull Visited<N> visited, @NotNull NodeHandler<N, R> handler) { 041 doDfs(node, neighbors, visited, handler); 042 return handler.result(); 043 } 044 045 public static <N> void dfsFromNode( 046 @NotNull N node, 047 @NotNull Neighbors<N> neighbors, 048 @NotNull Visited<N> visited 049 ) { 050 dfsFromNode(node, neighbors, visited, new AbstractNodeHandler<N, Void>() { 051 @Override 052 public Void result() { 053 return null; 054 } 055 }); 056 } 057 058 public static <N> List<N> topologicalOrder(@NotNull Iterable<N> nodes, @NotNull Neighbors<N> neighbors, @NotNull Visited<N> visited) { 059 TopologicalOrder<N> handler = new TopologicalOrder<N>(); 060 for (N node : nodes) { 061 doDfs(node, neighbors, visited, handler); 062 } 063 return handler.result(); 064 } 065 066 public static <N> List<N> topologicalOrder(@NotNull Iterable<N> nodes, @NotNull Neighbors<N> neighbors) { 067 return topologicalOrder(nodes, neighbors, new VisitedWithSet<N>()); 068 } 069 070 private static <N> void doDfs(@NotNull N current, @NotNull Neighbors<N> neighbors, @NotNull Visited<N> visited, @NotNull NodeHandler<N, ?> handler) { 071 if (!visited.checkAndMarkVisited(current)) return; 072 if (!handler.beforeChildren(current)) return; 073 074 for (N neighbor : neighbors.getNeighbors(current)) { 075 doDfs(neighbor, neighbors, visited, handler); 076 } 077 handler.afterChildren(current); 078 } 079 080 public interface NodeHandler<N, R> { 081 @KotlinSignature("fun beforeChildren(current: N): Boolean") 082 boolean beforeChildren(N current); 083 084 @KotlinSignature("fun afterChildren(current: N): Unit") 085 void afterChildren(N current); 086 087 R result(); 088 } 089 090 public interface Neighbors<N> { 091 @KotlinSignature("fun getNeighbors(current: N): Iterable<N>") 092 @NotNull 093 Iterable<? extends N> getNeighbors(N current); 094 } 095 096 public interface Visited<N> { 097 boolean checkAndMarkVisited(N current); 098 } 099 100 public static abstract class AbstractNodeHandler<N, R> implements NodeHandler<N, R> { 101 @Override 102 public boolean beforeChildren(N current) { 103 return true; 104 } 105 106 @Override 107 public void afterChildren(N current) { 108 } 109 } 110 111 public static class VisitedWithSet<N> implements Visited<N> { 112 private final Set<N> visited; 113 114 public VisitedWithSet() { 115 this(new HashSet<N>()); 116 } 117 118 public VisitedWithSet(@NotNull Set<N> visited) { 119 this.visited = visited; 120 } 121 122 @Override 123 public boolean checkAndMarkVisited(N current) { 124 return visited.add(current); 125 } 126 } 127 128 public static abstract class CollectingNodeHandler<N, R, C extends Iterable<R>> extends AbstractNodeHandler<N, C> { 129 @NotNull 130 protected final C result; 131 132 protected CollectingNodeHandler(@NotNull C result) { 133 this.result = result; 134 } 135 136 @Override 137 @NotNull 138 public C result() { 139 return result; 140 } 141 } 142 143 public static abstract class NodeHandlerWithListResult<N, R> extends CollectingNodeHandler<N, R, LinkedList<R>> { 144 protected NodeHandlerWithListResult() { 145 super(new LinkedList<R>()); 146 } 147 } 148 149 public static class TopologicalOrder<N> extends NodeHandlerWithListResult<N, N> { 150 @Override 151 public void afterChildren(N current) { 152 result.addFirst(current); 153 } 154 } 155 }