package search.graph;
/**
* Breadth First Graph search
*
* <p/>
* Copyright 1998-2012 by Mark Watson. All rights reserved.
* <p/>
* This software is can be used under either of the following licenses:
* <p/>
* 1. LGPL v3<br/>
* 2. Apache 2
* <p/>
*/
public class BreadthFirstSearch extends AbstractGraphSearch {
/** findPath - abstract method in super class */
public int [] findPath(int start_node, int goal_node) { // return an array of node indices
System.out.println("Entered BreadthFirstSearch.findPath(" +
start_node + ", " + goal_node + ")");
// data structures for depth first search:
boolean [] alreadyVisitedFlag = new boolean[numNodes];
int [] predecessor = new int[numNodes];
IntQueue queue = new IntQueue(numNodes + 2);
for (int i=0; i<numNodes; i++) {
alreadyVisitedFlag[i] = false;
predecessor[i] = -1;
}
alreadyVisitedFlag[start_node] = true;
queue.addToBackOfQueue(start_node);
outer: while (queue.isEmpty() == false) {
int head = queue.peekAtFrontOfQueue();
int [] connected = connected_nodes(head);
if (connected != null) {
for (int i=0; i<connected.length; i++) {
if (alreadyVisitedFlag[connected[i]] == false) {
predecessor[connected[i]] = head;
queue.addToBackOfQueue(connected[i]);
if (connected[i] == goal_node) break outer; // we are done
}
}
alreadyVisitedFlag[head] = true;
queue.removeFromQueue(); // ignore return value
}
}
// now calculate the shortest path from the predecessor array:
int [] ret = new int[numNodes + 1];
int count = 0;
ret[count++] = goal_node;
for (int i=0; i<numNodes; i++) {
ret[count] = predecessor[ret[count - 1]];
count++;
if (ret[count - 1] == start_node) break; // back to starting node
}
int [] ret2 = new int[count];
for (int i=0; i<count; i++) {
ret2[i] = ret[count - 1 - i];
}
return ret2;
}
protected class IntQueue {
public IntQueue(int num) {
queue = new int[num];
head = tail = 0;
len = num;
}
public IntQueue() {
this(400);
}
private int [] queue;
int tail, head, len;
public void addToBackOfQueue(int n) {
queue[tail] = n;
if (tail >= (len - 1)) {
tail = 0;
} else {
tail++;
}
}
public int removeFromQueue() {
int ret = queue[head];
if (head >= (len - 1)) {
head = 0;
} else {
head++;
}
return ret;
}
public boolean isEmpty() {
return head == (tail + 1);
}
public int peekAtFrontOfQueue() {
return queue[head];
}
}
protected int [] connected_nodes(int node) {
int [] ret = new int[AbstractGraphSearch.MAX];
int num = 0;
for (int n=0; n<numNodes; n++) {
boolean connected = false;
// See if there is a link between node 'node' and 'n':
for (int i=0; i<numLinks; i++) {
if (link_1[i] == node) {
if (link_2[i] == n) {
connected = true;
break;
}
}
if (link_2[i] == node) {
if (link_1[i] == n) {
connected = true;
break;
}
}
}
if (connected) {
ret[num++] = n;
}
}
if (num == 0) return null;
int [] ret2 = new int[num];
for (int i=0; i<num; i++) {
ret2[i] = ret[i];
}
return ret2;
}
}