Merge pull request #7770 from dupirefr/bael-3128

dupirefr/dupire.francois+pro@gmail.com [BAEL-3128] Breadth-First Search Algorithm in Java
This commit is contained in:
Erik Pragt
2019-10-13 09:43:10 +11:00
committed by GitHub
4 changed files with 205 additions and 0 deletions

View File

@@ -0,0 +1,54 @@
package com.baeldung.algorithms.breadthfirstsearch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
public class BreadthFirstSearchAlgorithm {
private static final Logger LOGGER = LoggerFactory.getLogger(BreadthFirstSearchAlgorithm.class);
public static <T> Optional<Tree<T>> search(T value, Tree<T> root) {
Queue<Tree<T>> queue = new ArrayDeque<>();
queue.add(root);
Tree<T> currentNode;
while (!queue.isEmpty()) {
currentNode = queue.remove();
LOGGER.info("Visited node with value: {}", currentNode.getValue());
if (currentNode.getValue().equals(value)) {
return Optional.of(currentNode);
} else {
queue.addAll(currentNode.getChildren());
}
}
return Optional.empty();
}
public static <T> Optional<Node<T>> search(T value, Node<T> start) {
Queue<Node<T>> queue = new ArrayDeque<>();
queue.add(start);
Node<T> currentNode;
Set<Node<T>> alreadyVisited = new HashSet<>();
while (!queue.isEmpty()) {
currentNode = queue.remove();
LOGGER.info("Visited node with value: {}", currentNode.getValue());
if (currentNode.getValue().equals(value)) {
return Optional.of(currentNode);
} else {
alreadyVisited.add(currentNode);
queue.addAll(currentNode.getNeighbors());
queue.removeAll(alreadyVisited);
}
}
return Optional.empty();
}
}

View File

@@ -0,0 +1,31 @@
package com.baeldung.algorithms.breadthfirstsearch;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class Node<T> {
private T value;
private Set<Node<T>> neighbors;
public Node(T value) {
this.value = value;
this.neighbors = new HashSet<>();
}
public T getValue() {
return value;
}
public Set<Node<T>> getNeighbors() {
return Collections.unmodifiableSet(neighbors);
}
public void connect(Node<T> node) {
if (this == node) throw new IllegalArgumentException("Can't connect node to itself");
this.neighbors.add(node);
node.neighbors.add(this);
}
}

View File

@@ -0,0 +1,34 @@
package com.baeldung.algorithms.breadthfirstsearch;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Tree<T> {
private T value;
private List<Tree<T>> children;
private Tree(T value) {
this.value = value;
this.children = new ArrayList<>();
}
public static <T> Tree<T> of(T value) {
return new Tree<>(value);
}
public T getValue() {
return value;
}
public List<Tree<T>> getChildren() {
return Collections.unmodifiableList(children);
}
public Tree<T> addChild(T value) {
Tree<T> newChild = new Tree<>(value);
children.add(newChild);
return newChild;
}
}

View File

@@ -0,0 +1,86 @@
package com.baeldung.algorithms.breadthfirstsearch;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class BreadthFirstSearchAlgorithmUnitTest {
private Tree<Integer> root;
private Tree<Integer> rootFirstChild;
private Tree<Integer> depthMostChild;
private Tree<Integer> rootSecondChild;
private Node<Integer> start;
private Node<Integer> firstNeighbor;
private Node<Integer> firstNeighborNeighbor;
private Node<Integer> secondNeighbor;
@Test
void givenTree_whenSearchTen_thenRoot() {
initTree();
assertThat(BreadthFirstSearchAlgorithm.search(10, root)).isPresent().contains(root);
}
@Test
void givenTree_whenSearchThree_thenDepthMostValue() {
initTree();
assertThat(BreadthFirstSearchAlgorithm.search(3, root)).isPresent().contains(depthMostChild);
}
@Test
void givenTree_whenSearchFour_thenRootSecondChild() {
initTree();
assertThat(BreadthFirstSearchAlgorithm.search(4, root)).isPresent().contains(rootSecondChild);
}
@Test
void givenTree_whenSearchFive_thenNotFound() {
initTree();
assertThat(BreadthFirstSearchAlgorithm.search(5, root)).isEmpty();
}
private void initTree() {
root = Tree.of(10);
rootFirstChild = root.addChild(2);
depthMostChild = rootFirstChild.addChild(3);
rootSecondChild = root.addChild(4);
}
@Test
void givenNode_whenSearchTen_thenStart() {
initNode();
assertThat(BreadthFirstSearchAlgorithm.search(10, firstNeighborNeighbor)).isPresent().contains(start);
}
@Test
void givenNode_whenSearchThree_thenNeighborNeighbor() {
initNode();
assertThat(BreadthFirstSearchAlgorithm.search(3, firstNeighborNeighbor)).isPresent().contains(firstNeighborNeighbor);
}
@Test
void givenNode_whenSearchFour_thenSecondNeighbor() {
initNode();
assertThat(BreadthFirstSearchAlgorithm.search(4, firstNeighborNeighbor)).isPresent().contains(secondNeighbor);
}
@Test
void givenNode_whenSearchFive_thenNotFound() {
initNode();
assertThat(BreadthFirstSearchAlgorithm.search(5, firstNeighborNeighbor)).isEmpty();
}
private void initNode() {
start = new Node<>(10);
firstNeighbor = new Node<>(2);
start.connect(firstNeighbor);
firstNeighborNeighbor = new Node<>(3);
firstNeighbor.connect(firstNeighborNeighbor);
firstNeighborNeighbor.connect(start);
secondNeighbor = new Node<>(4);
start.connect(secondNeighbor);
}
}