【题目】
对于一个有向图,请实现一个算法,找出两点之间是否存在一条路径。
给定图中的两个结点的指针UndirectedGraphNode* a,UndirectedGraphNode* b(请不要在意数据类型,图是有向图),请返回一个bool,代表两点之间是否存在一条路径(a到b或b到a)。
【代码】
import java.util.*; /* public class UndirectedGraphNode { int label = 0; UndirectedGraphNode left = null; UndirectedGraphNode right = null; ArrayList<UndirectedGraphNode> neighbors = new ArrayList<UndirectedGraphNode>(); public UndirectedGraphNode(int label) { this.label = label; } }*/ public class Path { //将访问的结点标记为true Map<UndirectedGraphNode, Boolean> visitedMap = new HashMap<>(); public boolean checkPath(UndirectedGraphNode a, UndirectedGraphNode b) { /*if (checkDFS(a, b)) { return true; } else { visitedMap.clear(); return checkDFS(b, a); }*/ return checkBFS(a, b) || checkBFS(b, a); } //深度优先搜索(递归) public boolean checkDFS(UndirectedGraphNode a, UndirectedGraphNode b){ if(a == null || b == null) return false; if (a == b) return true; visitedMap.put(a, true); for (UndirectedGraphNode neighborNode : a.neighbors ){ //若当前结点neighborNode 没有被访问到,且结点的值与b相同 //则表示a邻结点neighborNode 与 b相通,即a与b相通 if(!visitedMap.containsKey(neighborNode) && checkDFS(neighborNode, b)){ return true; } } return false; } //深度优先搜索(递归) public boolean checkBFS(UndirectedGraphNode a, UndirectedGraphNode b){ if(a == null || b == null) return false; if (a == b) return true; Queue<UndirectedGraphNode> queue = new LinkedList<>(); //将访问的结点标记为true Map<UndirectedGraphNode, Boolean> visitedMap2 = new HashMap<>(); visitedMap2.put(a, true); queue.offer(a); while (!queue.isEmpty()){ //弹出队列的头结点 UndirectedGraphNode node = queue.poll(); //遍历该结点的邻结点 for(UndirectedGraphNode neighboreNode : node.neighbors){ if (!visitedMap2.containsKey(neighboreNode)){ if(neighboreNode == b){ return true; } visitedMap2.put(neighboreNode, true); queue.offer(neighboreNode); } } } return false; } }
【解析】
深度优先遍历(DFS):从图中某个顶点v出发,访问此顶点,然后从v的未被访问的邻结点出发深度优先遍历图,直至图中所有和v有路径相通的顶点都被访问到。
若图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点,重复上述过程。
遍历规则:不断地沿着顶点的深度方向遍历。顶点的深度方向是指它的邻接点方向。
广度优先遍历(BFS):类似于树的层序遍历。先访问完当前顶点的所有邻接点。(应该看得出广度的意思)
先访问顶点的邻接点先于后访问顶点的邻接点被访问。
深度优先遍历适合目标比较明确,以找到目标为主要目的的情况;
广度优先遍历更适合在不断扩大范围找到相对最优解的情况。