广度优先算法
对于无向连通图,广度优先搜索是从图的某个顶点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()); } } }
执行结果如下: