邻接矩阵可使用一个二维数组来表示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 Queue<Integer> queue = new LinkedList<>(); // 栈,用于DFS private Stack<Integer> stack = new Stack<>(); private Map<Integer, Integer> dependencyMap = new HashMap<>(); public Graph(Vertex[] vertices, int[][] matrix) { this.vertices = vertices; this.matrix = matrix; } // 找到未访问过的邻接点 public List<Integer> getUnvisitedVertex(int i) { List<Integer> 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<Integer> 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<Integer> 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<Integer> 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-->v0node
邻接表可使用数组+链表,链表+链表,哈希表等等数据结构来表示。在java中,map结构很是适合表示邻接表数组
public class GraphTest { public static void main(String[] args){ //初始化先创建起各个节点信息,以及对应的直接子节点列表 HashMap<String,String[]> map = 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 + "\n"); List<Node> searchPath = new ArrayList<Node>(); 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<String,String[]> map) { List<String> hasSearchList = new ArrayList<String>(); LinkedList<Node> queue = new LinkedList<Node>(); queue.offer(new Node(startId,null)); while(!queue.isEmpty()) { Node node = queue.poll(); if(hasSearchList.contains(node.id)) { //跳过已经搜索过的,避免重复或者死循环 continue; } System.out.print("判断节点:" + node.id +"\n"); 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<Node> childs = new ArrayList<Node>(); public Node(String id,Node parent) { this.id = id; this.parent = parent; } } }
打印:
判断节点:V0
判断节点:V2
判断节点:V3
判断节点:V1
判断节点:V4
找到了目标节点:V4
步数最短:V0-->V2-->V4数据结构