Fixed the path finding algos a bit
This commit is contained in:
parent
0f85e1b4dd
commit
c161e4bdd8
11 changed files with 240 additions and 205 deletions
47
src/zutil/algo/path/BreadthFirstSearch.java
Normal file
47
src/zutil/algo/path/BreadthFirstSearch.java
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
package zutil.algo.path;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
* A class that uses BFS to find a path
|
||||
*
|
||||
* @author Ziver
|
||||
*/
|
||||
public class BreadthFirstSearch implements PathFinder{
|
||||
|
||||
/**
|
||||
* Returns the first path to the destination
|
||||
*
|
||||
* @param start is the start Node
|
||||
* @param stop is the goal Node
|
||||
* @return A list with the path
|
||||
*/
|
||||
public LinkedList<PathNode> find(PathNode start, PathNode stop){
|
||||
Queue<PathNode> queue = new LinkedList<PathNode>();
|
||||
HashSet<PathNode> visited = new HashSet<PathNode>();
|
||||
|
||||
queue.add(start);
|
||||
visited.add( start );
|
||||
|
||||
PathNode tmp;
|
||||
while(!queue.isEmpty()){
|
||||
tmp = queue.poll();
|
||||
|
||||
for(PathNode next : tmp.getNeighbors()){
|
||||
if(!visited.contains( next ) && tmp.getNeighborCost(next) > 0){
|
||||
queue.add(next);
|
||||
visited.add( next );
|
||||
next.setParentNeighbor(tmp);
|
||||
|
||||
if(next.equals(stop)){
|
||||
return stop.traversTo(start);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new LinkedList<PathNode>();
|
||||
}
|
||||
}
|
||||
51
src/zutil/algo/path/DepthFirstSearch.java
Normal file
51
src/zutil/algo/path/DepthFirstSearch.java
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
package zutil.algo.path;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
* A PathFinder class implemented with DFS
|
||||
*
|
||||
* @author Ziver
|
||||
*/
|
||||
public class DepthFirstSearch {
|
||||
private HashSet<PathNode> visited = new HashSet<PathNode>();
|
||||
|
||||
/**
|
||||
* Returns the first path to the destination
|
||||
*
|
||||
* @param start Start Node
|
||||
* @param stop Stop Node
|
||||
* @return A list with the path
|
||||
*/
|
||||
public LinkedList<PathNode> find(PathNode start, PathNode stop){
|
||||
visited.clear();
|
||||
PathNode node = dfs(start, stop);
|
||||
return node.traversTo( start );
|
||||
}
|
||||
|
||||
/**
|
||||
* The DepthFirstSearch algorithm
|
||||
* @param node The node to search from
|
||||
* @return The stop PathNode if a path was found else null
|
||||
*/
|
||||
private PathNode dfs(PathNode node, PathNode stop){
|
||||
visited.add( node );
|
||||
if(node.equals(stop)){
|
||||
return node;
|
||||
}
|
||||
|
||||
for(PathNode next : node.getNeighbors()){
|
||||
if(!visited.contains( next ) && node.getNeighborCost(next) > 0){
|
||||
next.setParentNeighbor(node);
|
||||
PathNode tmp = dfs(next, stop);
|
||||
if(tmp != null){
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
21
src/zutil/algo/path/PathFinder.java
Normal file
21
src/zutil/algo/path/PathFinder.java
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
package zutil.algo.path;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* All path finding algorithms should implement this interface
|
||||
*
|
||||
* @author Ziver
|
||||
*/
|
||||
public interface PathFinder {
|
||||
|
||||
/**
|
||||
* Starts the search for the path from the start
|
||||
* node to the goal.
|
||||
*
|
||||
* @param start is the starting point of the search
|
||||
* @param goal is the search goal
|
||||
* @return a LinkedList of the path, empty list if no path was found
|
||||
*/
|
||||
public LinkedList<PathNode> find(PathNode start, PathNode goal);
|
||||
}
|
||||
|
|
@ -1,17 +1,36 @@
|
|||
package zutil.algo.path;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
|
||||
public interface PathNode {
|
||||
|
||||
public void setVisited(boolean b);
|
||||
|
||||
public boolean visited();
|
||||
|
||||
/**
|
||||
* @return an Iterator with all its neighbors
|
||||
*/
|
||||
public Iterable<PathNode> getNeighbors();
|
||||
|
||||
/**
|
||||
* @param neighbor is the neighbor
|
||||
* @return the cost to the neighbor
|
||||
*/
|
||||
public int getNeighborCost(PathNode neighbor);
|
||||
|
||||
public void setSourceNeighbor(PathNode neighbor);
|
||||
/**
|
||||
* Sets the parent node to this one
|
||||
*/
|
||||
public void setParentNeighbor(PathNode parent);
|
||||
|
||||
public PathNode getSourceNeighbor();
|
||||
/**
|
||||
* @return the parent node
|
||||
*/
|
||||
public PathNode getParentNeighbor();
|
||||
|
||||
/**
|
||||
* Traverses the parent tree and returns the path.
|
||||
*
|
||||
* @param goal is the node to reach
|
||||
* @return the path to the goal, empty list if there is no goal
|
||||
*/
|
||||
public LinkedList<PathNode> traversTo(PathNode goal);
|
||||
}
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
package zutil.algo.path;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class PathNodeDefault implements PathNode{
|
||||
private HashMap<PathNode,Integer> neighbors;
|
||||
private PathNode neighbor;
|
||||
private boolean visited;
|
||||
|
||||
public PathNodeDefault(){
|
||||
neighbors = new HashMap<PathNode,Integer>();
|
||||
visited = false;
|
||||
}
|
||||
|
||||
public void setVisited(boolean b){
|
||||
visited = b;
|
||||
}
|
||||
|
||||
public int getNeighborCost(PathNode neighbor) {
|
||||
return neighbors.get(neighbor);
|
||||
}
|
||||
|
||||
public Iterable<PathNode> getNeighbors() {
|
||||
return neighbors.keySet();
|
||||
}
|
||||
|
||||
public boolean visited() {
|
||||
return visited;
|
||||
}
|
||||
|
||||
public void setSourceNeighbor(PathNode n) {
|
||||
neighbor = n;
|
||||
}
|
||||
|
||||
public PathNode getSourceNeighbor() {
|
||||
return neighbor;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,95 +0,0 @@
|
|||
package zutil.algo.path;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
/**
|
||||
* A class for simple path finding algorithms
|
||||
*
|
||||
* @author Ziver
|
||||
*/
|
||||
public class SimplePathFinder {
|
||||
|
||||
/**
|
||||
* Returns the first path to the destination
|
||||
*
|
||||
* @param start Start Node
|
||||
* @param stop Stop Node
|
||||
* @return A list with the path
|
||||
*/
|
||||
public LinkedList<PathNode> BreadthFirstSearch(PathNode start, PathNode stop){
|
||||
Queue<PathNode> queue = new LinkedList<PathNode>();
|
||||
|
||||
queue.add(start);
|
||||
start.setVisited(true);
|
||||
|
||||
PathNode tmp;
|
||||
while(!queue.isEmpty()){
|
||||
tmp = queue.poll();
|
||||
|
||||
for(PathNode next : tmp.getNeighbors()){
|
||||
if(!next.visited() && tmp.getNeighborCost(next) > 0){
|
||||
queue.add(next);
|
||||
next.setVisited(true);
|
||||
next.setSourceNeighbor(tmp);
|
||||
|
||||
if(next.equals(stop)){
|
||||
LinkedList<PathNode> path = new LinkedList<PathNode>();
|
||||
for(PathNode current=stop; !current.equals(start) ;current = current.getSourceNeighbor()){
|
||||
path.addFirst(current);
|
||||
}
|
||||
path.addFirst(start);
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new LinkedList<PathNode>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first path to the destination
|
||||
*
|
||||
* @param start Start Node
|
||||
* @param stop Stop Node
|
||||
* @return A list with the path
|
||||
*/
|
||||
public LinkedList<PathNode> DepthFirstSearch(PathNode start, PathNode stop){
|
||||
LinkedList<PathNode> path = new LinkedList<PathNode>();
|
||||
PathNode current = DepthFirstSearchInternal(start, stop);
|
||||
while(current != null){
|
||||
path.addFirst(current);
|
||||
current = current.getSourceNeighbor();
|
||||
if(current.equals(start)){
|
||||
path.addFirst(start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
* The DepthFirstSearch algorithm
|
||||
* @param node The node to search from
|
||||
* @return The stop PathNode if a path was found else null
|
||||
*/
|
||||
private PathNode DepthFirstSearchInternal(PathNode node, PathNode stop){
|
||||
node.setVisited(true);
|
||||
if(node.equals(stop)){
|
||||
return node;
|
||||
}
|
||||
|
||||
for(PathNode next : node.getNeighbors()){
|
||||
if(!next.visited() && node.getNeighborCost(next) > 0){
|
||||
next.setSourceNeighbor(node);
|
||||
PathNode tmp = DepthFirstSearchInternal(next, stop);
|
||||
if(tmp != null){
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
49
src/zutil/algo/path/StandardPathNode.java
Normal file
49
src/zutil/algo/path/StandardPathNode.java
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
package zutil.algo.path;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* An standard implementation of PathNode
|
||||
* @author Ziver
|
||||
*
|
||||
*/
|
||||
public class StandardPathNode implements PathNode{
|
||||
private HashMap<PathNode,Integer> neighbors;
|
||||
private PathNode parent;
|
||||
|
||||
public StandardPathNode(){
|
||||
neighbors = new HashMap<PathNode,Integer>();
|
||||
}
|
||||
|
||||
public int getNeighborCost(PathNode neighbor) {
|
||||
return neighbors.get(neighbor);
|
||||
}
|
||||
|
||||
public Iterable<PathNode> getNeighbors() {
|
||||
return neighbors.keySet();
|
||||
}
|
||||
|
||||
public PathNode getParentNeighbor() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public void setParentNeighbor(PathNode parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public LinkedList<PathNode> traversTo(PathNode goal) {
|
||||
LinkedList<PathNode> path = new LinkedList<PathNode>();
|
||||
PathNode current = this;
|
||||
while(current != null){
|
||||
path.addFirst(current);
|
||||
current = current.getParentNeighbor();
|
||||
if(goal.equals( current )){
|
||||
path.addFirst( goal );
|
||||
return path;
|
||||
}
|
||||
}
|
||||
return new LinkedList<PathNode>();
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue