* Adding node and cycle detection by hashing

* Adding implementation for all algorithms for cycle detection and removal

* Applying formatting rules

* Refactoring methods and adding more tests

* Fixing infinite loop corner case
This commit is contained in:
deep20jain
2017-09-08 22:53:55 +05:30
committed by Zeger Hendrikse
parent 35ac22c947
commit cccd6a3eab
14 changed files with 153 additions and 115 deletions

View File

@@ -2,19 +2,22 @@ package com.baeldung.algorithms.linkedlist;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(value = Parameterized.class)
public class CycleDetectionBruteForceTest extends CycleDetectionTestBase {
boolean cycleExists;
Node<Integer> head;
@Test
public void givenNormalList_dontDetectLoop() {
Node<Integer> root = createList();
Assert.assertFalse(CycleDetectionBruteForce.detectCycle(root));
public CycleDetectionBruteForceTest(Node<Integer> head, boolean cycleExists) {
super();
this.cycleExists = cycleExists;
this.head = head;
}
@Test
public void givenCyclicList_detectLoop() {
Node<Integer> root = createList();
createLoop(root);
Assert.assertTrue(CycleDetectionBruteForce.detectCycle(root));
public void givenList_detectLoop() {
Assert.assertEquals(cycleExists, CycleDetectionBruteForce.detectCycle(head).cycleExists);
}
}

View File

@@ -2,19 +2,22 @@ package com.baeldung.algorithms.linkedlist;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(value = Parameterized.class)
public class CycleDetectionByFastAndSlowIteratorsTest extends CycleDetectionTestBase {
boolean cycleExists;
Node<Integer> head;
@Test
public void givenNormalList_dontDetectLoop() {
Node<Integer> root = createList();
Assert.assertFalse(CycleDetectionByFastAndSlowIterators.detectCycle(root));
public CycleDetectionByFastAndSlowIteratorsTest(Node<Integer> head, boolean cycleExists) {
super();
this.cycleExists = cycleExists;
this.head = head;
}
@Test
public void givenCyclicList_detectLoop() {
Node<Integer> root = createList();
createLoop(root);
Assert.assertTrue(CycleDetectionByFastAndSlowIterators.detectCycle(root));
public void givenList_detectLoop() {
Assert.assertEquals(cycleExists, CycleDetectionByFastAndSlowIterators.detectCycle(head).cycleExists);
}
}

View File

@@ -2,19 +2,22 @@ package com.baeldung.algorithms.linkedlist;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(value = Parameterized.class)
public class CycleDetectionByHashingTest extends CycleDetectionTestBase {
boolean cycleExists;
Node<Integer> head;
@Test
public void givenNormalList_dontDetectLoop() {
Node<Integer> root = createList();
Assert.assertFalse(CycleDetectionByHashing.detectCycle(root));
public CycleDetectionByHashingTest(Node<Integer> head, boolean cycleExists) {
super();
this.cycleExists = cycleExists;
this.head = head;
}
@Test
public void givenCyclicList_detectLoop() {
Node<Integer> root = createList();
createLoop(root);
Assert.assertTrue(CycleDetectionByHashing.detectCycle(root));
public void givenList_detectLoop() {
Assert.assertEquals(cycleExists, CycleDetectionByHashing.detectCycle(head).cycleExists);
}
}

View File

@@ -1,7 +1,22 @@
package com.baeldung.algorithms.linkedlist;
import java.util.Arrays;
import java.util.Collection;
import org.junit.runners.Parameterized.Parameters;
public class CycleDetectionTestBase {
@Parameters
public static Collection<Object[]> getLists() {
return Arrays.asList(new Object[][] {
{ createList(), false },
{ createListWithLoop(), true },
{ createListWithFullCycle(), true },
{ createListWithSingleNodeInCycle(), true }
});
}
public static Node<Integer> createList() {
Node<Integer> root = Node.createNewNode(10, null);
@@ -13,6 +28,26 @@ public class CycleDetectionTestBase {
return root;
}
public static Node<Integer> createListWithLoop() {
Node<Integer> node = createList();
createLoop(node);
return node;
}
public static Node<Integer> createListWithFullCycle() {
Node<Integer> head = createList();
Node<Integer> tail = Node.getTail(head);
tail.next = head;
return head;
}
public static Node<Integer> createListWithSingleNodeInCycle() {
Node<Integer> head = createList();
Node<Integer> tail = Node.getTail(head);
tail.next = tail;
return head;
}
public static void createLoop(Node<Integer> root) {
Node<Integer> tail = Node.getTail(root);

View File

@@ -2,20 +2,23 @@ package com.baeldung.algorithms.linkedlist;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(value = Parameterized.class)
public class CycleRemovalBruteForceTest extends CycleDetectionTestBase {
boolean cycleExists;
Node<Integer> head;
@Test
public void givenNormalList_dontDetectLoop() {
Node<Integer> root = createList();
Assert.assertFalse(CycleRemovalBruteForce.detectAndRemoveCycle(root));
public CycleRemovalBruteForceTest(Node<Integer> head, boolean cycleExists) {
super();
this.cycleExists = cycleExists;
this.head = head;
}
@Test
public void givenCyclicList_detectAndRemoveLoop() {
Node<Integer> root = createList();
createLoop(root);
Assert.assertTrue(CycleRemovalBruteForce.detectAndRemoveCycle(root));
Assert.assertFalse(CycleDetectionByFastAndSlowIterators.detectCycle(root));
public void givenList_ifLoopExists_thenDetectAndRemoveLoop() {
Assert.assertEquals(cycleExists, CycleRemovalBruteForce.detectAndRemoveCycle(head));
Assert.assertFalse(CycleDetectionByFastAndSlowIterators.detectCycle(head).cycleExists);
}
}

View File

@@ -2,20 +2,23 @@ package com.baeldung.algorithms.linkedlist;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(value = Parameterized.class)
public class CycleRemovalByCountingLoopNodesTest extends CycleDetectionTestBase {
boolean cycleExists;
Node<Integer> head;
@Test
public void givenNormalList_dontDetectLoop() {
Node<Integer> root = createList();
Assert.assertFalse(CycleRemovalByCountingLoopNodes.detectAndRemoveCycle(root));
public CycleRemovalByCountingLoopNodesTest(Node<Integer> head, boolean cycleExists) {
super();
this.cycleExists = cycleExists;
this.head = head;
}
@Test
public void givenCyclicList_detectAndRemoveLoop() {
Node<Integer> root = createList();
createLoop(root);
Assert.assertTrue(CycleRemovalByCountingLoopNodes.detectAndRemoveCycle(root));
Assert.assertFalse(CycleDetectionByFastAndSlowIterators.detectCycle(root));
public void givenList_ifLoopExists_thenDetectAndRemoveLoop() {
Assert.assertEquals(cycleExists, CycleRemovalByCountingLoopNodes.detectAndRemoveCycle(head));
Assert.assertFalse(CycleDetectionByFastAndSlowIterators.detectCycle(head).cycleExists);
}
}

View File

@@ -2,20 +2,23 @@ package com.baeldung.algorithms.linkedlist;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(value = Parameterized.class)
public class CycleRemovalWithoutCountingLoopNodesTest extends CycleDetectionTestBase {
boolean cycleExists;
Node<Integer> head;
@Test
public void givenNormalList_dontDetectLoop() {
Node<Integer> root = createList();
Assert.assertFalse(CycleRemovalWithoutCountingLoopNodes.detectAndRemoveCycle(root));
public CycleRemovalWithoutCountingLoopNodesTest(Node<Integer> head, boolean cycleExists) {
super();
this.cycleExists = cycleExists;
this.head = head;
}
@Test
public void givenCyclicList_detectAndRemoveLoop() {
Node<Integer> root = createList();
createLoop(root);
Assert.assertTrue(CycleRemovalWithoutCountingLoopNodes.detectAndRemoveCycle(root));
Assert.assertFalse(CycleDetectionByFastAndSlowIterators.detectCycle(root));
public void givenList_ifLoopExists_thenDetectAndRemoveLoop() {
Assert.assertEquals(cycleExists, CycleRemovalWithoutCountingLoopNodes.detectAndRemoveCycle(head));
Assert.assertFalse(CycleDetectionByFastAndSlowIterators.detectCycle(head).cycleExists);
}
}