广度优先算法

对于无向连通图,广度优先搜索是从图的某个顶点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());
		}

	}
}

执行结果如下:

posted on 2015-11-19 16:51  奈何作贼  阅读(287)  评论(0编辑  收藏  举报

导航