diff --git a/platform/platform-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java b/platform/platform-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java index 7e6e3d35a001..74cd55be6d95 100644 --- a/platform/platform-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java +++ b/platform/platform-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java @@ -102,14 +102,12 @@ public class KShortestPathsFinder { for (int j = 1; j < heapNodes.size(); j++) { HeapNode heapNode = heapNodes.get(j); HeapNode parent = heapNodes.get((j+1)/2 - 1); - heapNode.myParent = parent; parent.myChildren[(j+1) % 2] = heapNode; } for (int j = heapNodes.size() / 2 - 1; j >= 0; j--) { heapify(heapNodes.get(j)); } root.myChildren[2] = heapNodes.get(0); - root.myChildren[2].myParent = root; } } } @@ -271,38 +269,37 @@ public class KShortestPathsFinder { public Heap insert(HeapNode node) { int pos = mySize + 1; int pow = 1; - while (pos > pow << 2) { + while (pos >= pow << 2) { pow <<= 1; } - HeapNode place = myRoot; + HeapNode newRoot = myRoot.copy(); + HeapNode place = newRoot; + List> parents = new ArrayList>(); while (true) { + parents.add(place); final int ind = (pos & pow) != 0 ? 1 : 0; if (pow == 1) { - HeapNode placeCopy = place.copy(); - placeCopy.myChildren[ind] = node; - node.myParent = placeCopy; + place.myChildren[ind] = node; break; } - place = place.myChildren[ind]; + HeapNode copy = place.myChildren[ind].copy(); + place.myChildren[ind] = copy; + place = copy; pow >>= 1; } - while (true) { - final HeapNode parent = node.myParent; - if (parent == null || parent.myEdge.getDelta() < node.myEdge.getDelta()) { + + for (int i = parents.size() - 1; i >= 0; i--) { + HeapNode parent = parents.get(i); + if (parent.myEdge.getDelta() < node.myEdge.getDelta()) { break; } - final HeapNode parentCopy = parent.copy(); - final GraphEdge t = parentCopy.myEdge; - parentCopy.myEdge = node.myEdge; + final GraphEdge t = parent.myEdge; + parent.myEdge = node.myEdge; node.myEdge = t; - final HeapNode t2 = parentCopy.myChildren[2]; - parentCopy.myChildren[2] = node.myChildren[2]; + final HeapNode t2 = parent.myChildren[2]; + parent.myChildren[2] = node.myChildren[2]; node.myChildren[2] = t2; - node = parentCopy; - } - HeapNode newRoot = node; - while (newRoot.myParent != null) { - newRoot = newRoot.myParent; + node = parent; } return new Heap(mySize + 1, newRoot); } @@ -310,7 +307,6 @@ public class KShortestPathsFinder { private static class HeapNode { public HeapNode[] myChildren; - public HeapNode myParent; public GraphEdge myEdge; private HeapNode(GraphEdge edge) { @@ -321,7 +317,6 @@ public class KShortestPathsFinder { public HeapNode(HeapNode node) { myEdge = node.myEdge; myChildren = node.myChildren.clone(); - myParent = node.myParent; } public HeapNode copy() { diff --git a/platform/platform-tests/testSrc/com/intellij/util/graph/KShortestPathsFinderTest.java b/platform/platform-tests/testSrc/com/intellij/util/graph/KShortestPathsFinderTest.java index 71b8809924dd..c7d816d90080 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/graph/KShortestPathsFinderTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/graph/KShortestPathsFinderTest.java @@ -136,7 +136,29 @@ public class KShortestPathsFinderTest extends GraphTestCase { graph.put("f", "t"); graph.put("t", ""); doTest(graph, "sabct", "sadeft", "sabdeft", "sabcdeft"); + } + public void testBigHeap() { + final Map graph = new HashMap(); + graph.put("s", "lo"); + graph.put("a", "tb"); + graph.put("b", "t"); + graph.put("c", "ad"); + graph.put("d", "e"); + graph.put("e", "b"); + graph.put("f", "cg"); + graph.put("g", "h"); + graph.put("h", "d"); + graph.put("i", "fj"); + graph.put("j", "k"); + graph.put("k", "g"); + graph.put("l", "im"); + graph.put("m", "n"); + graph.put("n", "j"); + graph.put("o", "p"); + graph.put("p", "m"); + graph.put("t", ""); + doTest(graph, "slifcat", "slifcabt", "slifcdebt", "slifghdebt", "slijkghdebt", "slmnjkghdebt", "sopmnjkghdebt"); } private static void doTest(Map graph, String... expectedPaths) {