From 96079e5c48789af0b0dbbb8a1058fd414f7ac337 Mon Sep 17 00:00:00 2001 From: Vladimir Koshelev Date: Mon, 12 Mar 2018 12:31:19 +0300 Subject: [PATCH] GraphAlgorithmsImpl#collectOutsRecursively: use non-recursive traversal add tests for GraphAlgorithms#collectOutsRecursively (cherry picked from commit 02398dc) IDEA-CR-30465 --- .../util/graph/impl/GraphAlgorithmsImpl.java | 16 +++-- .../com/intellij/util/graph/CollectTest.java | 71 +++++++++++++++++++ 2 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 platform/platform-tests/testSrc/com/intellij/util/graph/CollectTest.java diff --git a/platform/core-impl/src/com/intellij/util/graph/impl/GraphAlgorithmsImpl.java b/platform/core-impl/src/com/intellij/util/graph/impl/GraphAlgorithmsImpl.java index 397b905ab023..90a512ba31bd 100644 --- a/platform/core-impl/src/com/intellij/util/graph/impl/GraphAlgorithmsImpl.java +++ b/platform/core-impl/src/com/intellij/util/graph/impl/GraphAlgorithmsImpl.java @@ -3,6 +3,7 @@ package com.intellij.util.graph.impl; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.util.Chunk; +import com.intellij.util.containers.Stack; import com.intellij.util.graph.*; import org.jetbrains.annotations.NotNull; @@ -96,10 +97,17 @@ public class GraphAlgorithmsImpl extends GraphAlgorithms { if (!set.add(start)) { return; } - Iterator iterator = graph.getOut(start); - while (iterator.hasNext()) { - Node node = iterator.next(); - collectOutsRecursively(graph, node, set); + final Stack stack = new Stack<>(); + stack.push(start); + while (!stack.empty()) { + final Node currentNode = stack.pop(); + final Iterator successorIterator = graph.getOut(currentNode); + while (successorIterator.hasNext()) { + Node successor = successorIterator.next(); + if (set.add(successor)) { + stack.push(successor); + } + } } } diff --git a/platform/platform-tests/testSrc/com/intellij/util/graph/CollectTest.java b/platform/platform-tests/testSrc/com/intellij/util/graph/CollectTest.java new file mode 100644 index 000000000000..84bf763b1ed5 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/util/graph/CollectTest.java @@ -0,0 +1,71 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.util.graph; + +import com.intellij.util.ArrayUtil; +import gnu.trove.THashMap; +import gnu.trove.THashSet; +import org.jetbrains.annotations.NotNull; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +public class CollectTest extends GraphTestCase { + + @Test + public void testSimple() { + Map graph = new THashMap<>(); + graph.put("a", "b"); + graph.put("b", "c"); + graph.put("c", "c"); + doTest(graph, "b", "b", "c"); + } + + @Test + public void testFull() { + Map graph = new THashMap<>(); + graph.put("a", "bcd"); + graph.put("b", "acd"); + graph.put("c", "abd"); + graph.put("d", "abc"); + doTest(graph, "a", "a", "b", "c", "d"); + } + + @Test + public void testVisitedNode() { + Map graph = new THashMap<>(); + graph.put("a", "bcd"); + graph.put("b", "acd"); + graph.put("c", "abd"); + graph.put("d", "abc"); + Set nodes = new THashSet<>(); + nodes.add("a"); + getAlgorithmsInstance().collectOutsRecursively(initGraph(graph), "a", nodes); + assertThat(nodes.size()).isEqualTo(1); + } + + @Test + public void testBigGraph() { + Map graph = new THashMap<>(); + List answer = new ArrayList<>(); + for (int i = 0; i < 10000; ++i) { + graph.put(String.valueOf((char)i), String.valueOf((char)(i + 1))); + answer.add(String.valueOf((char)i)); + } + graph.put(String.valueOf((char)10000), String.valueOf((char)0)); + answer.add(String.valueOf((char)10000)); + doTest(graph, "0", ArrayUtil.toStringArray(answer)); + } + + private static void doTest(final @NotNull Map graph, + final @NotNull String node, + final @NotNull String... expected) { + Set nodes = new THashSet<>(); + getAlgorithmsInstance().collectOutsRecursively(initGraph(graph), node, nodes); + assertThat(nodes).containsExactlyInAnyOrder(expected); + } +}