对于无向连通图,广度优先搜索是从图的某个顶点v0出发,在访问v0之后,依次搜索访问v0的各个未被访问过的邻接点w1,w2,…。然后顺序搜索访问w1的各未被访问过的邻接点,w2的各未被访问过的邻接点…。即从v0开始,由近至远,按层次依次访问与v0有路径相通且路径长度分别为1,2,…的顶点,直至连通图中所有顶点都被访问一次。
广度优先搜索在搜索访问一层时,需要记住已被访问的顶点,以便在访问下层顶点时,从已被访问的顶点出发搜索访问其邻接点。所以在广度优先搜索中需要设置一个队列Queue,使已被访问的顶点顺序由队尾进入队列。在搜索访问下层顶点时,先从队首取出一个已被访问的上层顶点,再从该顶点出发搜索访问它的各个邻接点。
用java实现的深度优先算法代码如下:
import java.util.ArrayList;
import java.util.List;
/**
* 队列
*
* @author Thief
*
* @param <E>
*/
public class Queue<E> {
private List<E> queue = new ArrayList<E>();
/**
* 入队
*
* @param e
*/
public void enqueue(E e) {
queue.add(e);
}
/**
* 出队
*
* @param e
* 队首元素
*/
public E dequeue() {
E e = isEmpty() ? null : queue.get(0);
if (e != null) {
queue.remove(0);
}
return e;
}
/**
* 判断当前队列是否为空
*
* @return
*/
public boolean isEmpty() {
return queue.isEmpty();
}
}
/**
* 边
*
* @author Thief
*
*/
public class Edge {
public Edge(String vertexA, String vertexB) {
super();
this.vertexA = vertexA;
this.vertexB = vertexB;
}
/**
* 顶点A
*/
private String vertexA;
/**
* 顶点B
*/
private String vertexB;
/**
* 该边是否已经被访问
*/
boolean isVisited = false;
public String getVertexA() {
return vertexA;
}
public void setVertexA(String vertexA) {
this.vertexA = vertexA;
}
public String getVertexB() {
return vertexB;
}
public void setVertexB(String vertexB) {
this.vertexB = vertexB;
}
public boolean isVisited() {
return isVisited;
}
public void setVisited(boolean isVisited) {
this.isVisited = isVisited;
}
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 图
*
* @author Thief
*
*/
public class Graph {
/**
* 顶点
*/
private List<String> vertexList = new ArrayList<String>();
/**
* 边
*/
private Map<String, List<Edge>> edgeMap = new HashMap<String, List<Edge>>();
/**
* 向图中添加顶点
*
* @param vertex
* 顶点名字
* @throws Exception
* 当顶点已经存在时抛出异常
*/
public void addVertex(String vertex) throws Exception {
if (vertexList.contains(vertex)) {
throw new Exception("该顶点已经存在!");
} else {
vertexList.add(vertex);
}
}
/**
* 向图中添加边
*
* @param vertexName_A
* 顶点A的名字
* @param vertexName_B
* 顶点B的名字
* @throws Exception
* 顶点不存在或边已经存在时抛出异常
*/
public void addEdge(String vertexA, String vertexB) throws Exception {
if (!vertexList.contains(vertexA) || !vertexList.contains(vertexB)) {
throw new Exception("顶点不存在!");
}
if (containsEdge(vertexA, vertexB)) {
throw new Exception("边已经存在");
}
if (edgeMap.containsKey(vertexA)) {
List<Edge> list = edgeMap.get(vertexA);
list.add(new Edge(vertexA, vertexB));
} else {
List<Edge> list = new ArrayList<Edge>();
list.add(new Edge(vertexA, vertexB));
edgeMap.put(vertexA, list);
}
if (edgeMap.containsKey(vertexB)) {
List<Edge> list = edgeMap.get(vertexB);
list.add(new Edge(vertexB, vertexA));
} else {
List<Edge> list = new ArrayList<Edge>();
list.add(new Edge(vertexB, vertexA));
edgeMap.put(vertexB, list);
}
}
/**
* 判断图中该边是否已经存在
*
* @param vertexA
* 顶点A
* @param vertexB
* 顶点B
* @return 如果存在返回true,否则返回false
*/
private boolean containsEdge(String vertexA, String vertexB) {
boolean isExist = false;
if (edgeMap.containsKey(vertexA)) {
List<Edge> list = edgeMap.get(vertexA);
if (list.contains(new Edge(vertexA, vertexB))) {
isExist = true;
}
}
return isExist;
}
/**
* 广度优先搜索
*
* @param startVertex
* 起点
*/
public void BFS(String startVertex) {
Queue<String> queue = new Queue<String>();
queue.enqueue(startVertex);
System.out.println("搜索开始。。。");
System.out.print(startVertex);
while (!queue.isEmpty()) {
String vertex = queue.dequeue();
if (edgeMap.containsKey(vertex)) {
for (Edge item : edgeMap.get(vertex)) {
if (!item.isVisited) {
System.out.print(" --> ");
System.out.print(item.getVertexB());
item.isVisited = true;
for (Edge item2 : edgeMap.get(item.getVertexB())) {
if (item2.getVertexB().equals(vertex)) {
item2.isVisited = true;
break;
}
}
queue.enqueue(item.getVertexB());
}
}
}
}
System.out.println();
System.out.println("搜索结束。。。");
}
}
测试代码如下:
public class Test {
public static void main(String[] args) {
Graph graph = new Graph();
try {
graph.addVertex("A");
graph.addVertex("B");
graph.addVertex("C");
graph.addVertex("D");
graph.addVertex("E");
graph.addVertex("F");
graph.addVertex("G");
graph.addEdge("A", "B");
graph.addEdge("B", "C");
graph.addEdge("B", "D");
graph.addEdge("A", "E");
graph.addEdge("E", "F");
graph.addEdge("A", "G");
graph.BFS("A");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
执行结果如下:
