一、应用
深度优先:是否存在通路,寻找所有解。
广度优先遍历:寻求最优解,寻求最短路径
1.邻接矩阵JAVA代码实现邻接矩阵可以使用一个二维数组来表示
public class GraphTest { // 节点 public static class Vertex { public String name; private boolean isVisited; public Vertex(String name) { this.name = name; this.isVisited = false; } public void displayName() { System.out.println("name:" + name); } } // 图 public static class Graph { // 存节点数据 private Vertex[] vertices; // 矩阵 private int[][] matrix; // 队列,用于BFS private Queuequeue = new LinkedList<>(); // 栈,用于DFS private Stack stack = new Stack<>(); private Map dependencyMap = new HashMap<>(); public Graph(Vertex[] vertices, int[][] matrix) { this.vertices = vertices; this.matrix = matrix; } // 找到未访问过的邻接点 public List getUnvisitedVertex(int i) { List unvisitedVertices = new ArrayList<>(); for (int j = 0; j < matrix.length; j++) { if (matrix[i][j] > 0 && !vertices[j].isVisited) { unvisitedVertices.add(j); } } return unvisitedVertices; } // 广度优先 public void bfs(int vertex) { queue.offer(vertex); while (!queue.isEmpty()) { int v = queue.poll(); if (!vertices[v].isVisited) { vertices[v].displayName(); vertices[v].isVisited = true; List unvisitedVertices = getUnvisitedVertex(v); unvisitedVertices.forEach(uv -> { queue.offer(uv); dependencyMap.putIfAbsent(uv, v); }); } } } // 深度优先 public void dfs(int vertex) { stack.push(vertex); while (!stack.isEmpty()) { int v = stack.pop(); if (!vertices[v].isVisited) { vertices[v].displayName(); vertices[v].isVisited = true; List unvisitedVertices = getUnvisitedVertex(v); unvisitedVertices.forEach(uv -> stack.push(uv)); } } } // 深度优先递归实现 public void dfsRecursion(int vertex) { if (!vertices[vertex].isVisited) { vertices[vertex].displayName(); vertices[vertex].isVisited = true; List unvisitedVertices = getUnvisitedVertex(vertex); unvisitedVertices.forEach(this::dfsRecursion); } } public void printShortestPath(int start, int end) { bfs(start); String symbol = "-->"; StringBuilder sb = new StringBuilder(); sb.append(vertices[end].name); sb.append(symbol); while (dependencyMap.get(end) != null) { sb.append(vertices[dependencyMap.get(end)].name); sb.append(symbol); end = dependencyMap.get(end); } String path = sb.substring(0, sb.lastIndexOf(symbol)); System.out.println(path); } public void clear() { stack.clear(); queue.clear(); dependencyMap.clear(); for (int i = 0; i < vertices.length; i++) { vertices[i].isVisited = false; } } } public static void main(String[] args) { Vertex[] vertices = { new Vertex("v0"), new Vertex("v1"), new Vertex("v2"), new Vertex("v3"), new Vertex("v4") }; int[][] matrix = new int[][]{ {0, 0, 1, 1, 0}, {0, 0, 1, 0, 1}, {1, 1, 0, 0, 1}, {1, 0, 0, 0, 1}, {0, 1, 1, 1, 0} }; Graph graph = new Graph(vertices, matrix); System.out.println("广度优先搜索:"); graph.bfs(0); graph.clear(); System.out.println("深度优先搜索:"); graph.dfs(0); graph.clear(); System.out.println("递归深度优先搜索:"); graph.dfsRecursion(0); graph.clear(); System.out.println("打印最短路径:"); graph.printShortestPath(0, 4); } }
打印结果
广度优先搜索:
name:v0
name:v2
name:v3
name:v1
name:v4
深度优先搜索:
name:v0
name:v3
name:v4
name:v2
name:v1
递归深度优先搜索:
name:v0
name:v2
name:v1
name:v4
name:v3
打印最短路径:
name:v0
name:v2
name:v3
name:v1
name:v4
v4-->v2-->v0
邻接表可以使用数组+链表,链表+链表,哈希表等等数据结构来表示。在java中,map结构非常适合表示邻接表
public class GraphTest { public static void main(String[] args){ //初始化先建立起各个节点信息,以及对应的直接子节点列表 HashMapmap = new HashMap<>(); map.put("V0", new String[] {"V2","V3"}); map.put("V1", new String[] {"V2","V4"}); map.put("V2", new String[] {"V0","V1","V4"}); map.put("V3", new String[] {"V0","V4"}); map.put("V4", new String[] {"V1","V2","V3"}); //获取从A到H的最短路径节点链表 Node target = findTarget("V0","V4",map); //打印出最短路径的各个节点信息 printSearPath(target); } /** * 打印出到达节点target所经过的各个节点信息 * @param target */ static void printSearPath(Node target) { if (target != null) { System.out.print("找到了目标节点:" + target.id + " "); List searchPath = new ArrayList (); searchPath.add(target); Node node = target.parent; while(node!=null) { searchPath.add(node); node = node.parent; } String path = ""; for(int i=searchPath.size()-1;i>=0;i--) { path += searchPath.get(i).id; if(i!=0) { path += "-->"; } } System.out.print("步数最短:"+path); } else { System.out.print("未找到了目标节点"); } } /** * 从指定的开始节点 startId ,查询到目标节点targetId 的最短路径 * @param startId * @param targetId * @param map * @return */ static Node findTarget(String startId,String targetId,HashMap map) { List hasSearchList = new ArrayList (); LinkedList queue = new LinkedList (); queue.offer(new Node(startId,null)); while(!queue.isEmpty()) { Node node = queue.poll(); if(hasSearchList.contains(node.id)) { //跳过已经搜索过的,避免重复或者死循环 continue; } System.out.print("判断节点:" + node.id +" "); if (targetId.equals(node.id)) { return node; } hasSearchList.add(node.id); if (map.get(node.id) != null && map.get(node.id).length > 0) { for (String childId : map.get(node.id)) { queue.offer(new Node(childId,node)); } } } return null; } /** * 节点对象 * @author Administrator * */ static class Node{ //节点唯一id public String id; //该节点的直接父节点 public Node parent; //该节点的直接子节点 public List childs = new ArrayList (); public Node(String id,Node parent) { this.id = id; this.parent = parent; } } }
打印:
判断节点:V0
判断节点:V2
判断节点:V3
判断节点:V1
判断节点:V4
找到了目标节点:V4
步数最短:V0-->V2-->V4
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/75297.html
摘要:写在最前本次分享一下通过广度优先搜索解决八数码问题并展示其最短路径的动画效果。一个排列中逆序的总数就称为这个排列的逆序数。如果起始状态与结束状态的逆序数的奇偶性相同,则说明状态可达,反之亦然。 写在最前 本次分享一下通过广度优先搜索解决八数码问题并展示其最短路径的动画效果。 欢迎关注我的博客,不定期更新中—— 效果预览 该效果为从[[2, 6, 3],[4, 8, 0],[7, 1, ...
摘要:队列和广度优先搜索的一个常见应用是找出从根结点到目标结点的最短路径。然后在每一轮中,我们逐个处理已经在队列中的结点,并将所有邻居添加到队列中。这就是我们在中使用队列的原因。 队列和 BFS: 广度优先搜索(BFS)的一个常见应用是找出从根结点到目标结点的最短路径。 示例 这里我们提供一个示例来说明如何使用 BFS 来找出根结点 A 和目标结点 G 之间的最短路径。 showImg(h...
摘要:散列表上面的地图向我们展示了如何用广度优先搜索的思想找到北京到广州的最短路线。在广度优先搜索中,我们需要用到队列的这种思想来实现查找。建立了下面这个模型武汉广州西藏上海上海武汉广州代码完整实现,利用递归和广度优先搜索的思想实现。 什么是广度优先搜索? 如果只是是背概念,幼儿园的小朋友都能背下来念给你听。 假设看这篇文章的都和我一样是个前端工程师,我们要从广度优先搜索(BFS)中学到什么...
阅读 2331·2021-11-24 10:27
阅读 3576·2019-08-30 15:55
阅读 3340·2019-08-30 15:53
阅读 2341·2019-08-29 17:27
阅读 1427·2019-08-26 13:47
阅读 3547·2019-08-26 10:28
阅读 912·2019-08-23 15:59
阅读 2849·2019-08-23 15:19