一、图
1、介绍
图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
无向完全图:在无向图中,任意两个顶点之间都存在边。含有 n 个顶点的无向完全图有 n*(n - 1)/2 条边。
有向完全图:在有向图中,任意两个顶点之间都存在弧。含有 n 个顶点的有向完全图有 n*(n - 1)条边。
通常认为边或弧数小于 n*logn (n是顶点个数)的图为稀疏图,反之为稠密图。
2、图的存储结构
邻接矩阵:适用稠密图
无向图
有向图
网
邻接表:适用稀疏图
无向图
有向图-顶点当弧尾
有向图-顶点当弧头
有向图-网
3、图的遍历
深度优先遍历顺序为:1->2->4->8->5->3->6->7
广度优先遍历顺序为:1->2->3->4->5->6->7->8
深度优先遍历(DepthFirstSearch:DFS):类似于树的前序遍历
思想:略。
代码示例:见后
广度优先遍历(BreadthFirstSearch:BFS):类似于树的层序遍历
思想:需要一个辅助队列。
代码示例:深度优先、广度优先
1 public class Graph { 2 3 // 顶点集 4 private List<String> vertex; 5 // 邻接矩阵 6 private int[][] matrix; 7 8 public Graph(String[] vertex, int[][] matrix) { 9 if (vertex == null || vertex.length == 0 || matrix == null) { 10 return; 11 } 12 13 // 初始化顶点集 14 this.vertex = new ArrayList<>(Arrays.asList(vertex)); 15 16 // 初始化邻接矩阵 17 this.matrix = new int[vertex.length][vertex.length]; 18 for (int i = 0; i < vertex.length; i++) { 19 System.arraycopy(matrix[i], 0, this.matrix[i], 0, vertex.length); 20 } 21 } 22 23 // 深度优先遍历 24 public void dfs() { 25 // 记录某个结点是否被访问 26 boolean[] visited = new boolean[vertex.size()]; 27 for (int i = 0; i < vertex.size(); i++) { 28 if (!visited[i]) { 29 this.dfs(visited, i); 30 } 31 } 32 } 33 34 private void dfs(boolean[] visited, int i) { 35 System.out.print(vertex.get(i) + "->"); 36 visited[i] = true; 37 38 int w = this.getFirstNeighbor(i); 39 // 找到 40 while (w != -1) { 41 if (!visited[w]) { 42 dfs(visited, w); 43 } 44 // w已经被访问过 45 w = getNextNeighbor(i, w + 1); 46 } 47 48 } 49 50 // 广度优先遍历 51 public void bfs() { 52 // 记录某个结点是否被访问 53 boolean[] visited = new boolean[vertex.size()]; 54 for (int i = 0; i < vertex.size(); i++) { 55 if (!visited[i]) { 56 this.bfs(visited, i); 57 } 58 } 59 } 60 61 private void bfs(boolean[] visited, int i) { 62 System.out.print(vertex.get(i) + "->"); 63 visited[i] = true; 64 65 // 队列.记录结点访问顺序 66 Queue<Integer> queue = new LinkedList<>(); 67 queue.offer(i); 68 69 while (!queue.isEmpty()) { 70 final Integer u = queue.poll(); 71 72 // 得到u的第一个邻接结点的下标w 73 int w = this.getFirstNeighbor(u); 74 while (w != -1) { 75 if (!visited[w]) { 76 System.out.print(vertex.get(w) + "->"); 77 visited[w] = true; 78 queue.offer(w); 79 } 80 // 以u为前驱,找w后的下一个邻接点 81 w = this.getNextNeighbor(u, w + 1); 82 } 83 } 84 } 85 86 private int getFirstNeighbor(int index) { 87 return this.getNextNeighbor(index, 0); 88 } 89 90 // 根据前一个邻接结点的下标来获取下一个邻接结点 91 private int getNextNeighbor(int index, int v2) { 92 for (int j = v2; j < vertex.size(); j++) { 93 if (matrix[index][j] > 0) { 94 return j; 95 } 96 } 97 98 return -1; 99 } 100 101 // 显示图的邻接矩阵 102 public void showGraph() { 103 for (int[] link : this.matrix) { 104 System.out.println(Arrays.toString(link)); 105 } 106 } 107 108 }