鄰接矩陣可使用一個二維數組來表示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數據結構