zcq
    图的创建图解
    深度搜索(DFS)
    广度搜索(BFS)

    1. package com.atguigu.graph;
    2. import java.util.ArrayList;
    3. import java.util.Arrays;
    4. import java.util.LinkedList;
    5. public class Graph {
    6. private ArrayList<String> vertexList; //存储顶点集合
    7. private int[][] edges; //存储图对应的邻结矩阵
    8. private int numOfEdges; //表示边的数目
    9. //定义给数组boolean[], 记录某个结点是否被访问
    10. private boolean[] isVisited;
    11. public static void main(String[] args) {
    12. //测试一把图是否创建ok
    13. int n = 8; //结点的个数
    14. //String Vertexs[] = {"A", "B", "C", "D", "E"};
    15. String Vertexs[] = {"1", "2", "3", "4", "5", "6", "7", "8"};
    16. //创建图对象
    17. Graph graph = new Graph(n);
    18. //循环的添加顶点
    19. for(String vertex: Vertexs) {
    20. graph.insertVertex(vertex);
    21. }
    22. //添加边
    23. //A-B A-C B-C B-D B-E
    24. // graph.insertEdge(0, 1, 1); // A-B
    25. // graph.insertEdge(0, 2, 1); //
    26. // graph.insertEdge(1, 2, 1); //
    27. // graph.insertEdge(1, 3, 1); //
    28. // graph.insertEdge(1, 4, 1); //
    29. //更新边的关系
    30. graph.insertEdge(0, 1, 1);
    31. graph.insertEdge(0, 2, 1);
    32. graph.insertEdge(1, 3, 1);
    33. graph.insertEdge(1, 4, 1);
    34. graph.insertEdge(3, 7, 1);
    35. graph.insertEdge(4, 7, 1);
    36. graph.insertEdge(2, 5, 1);
    37. graph.insertEdge(2, 6, 1);
    38. graph.insertEdge(5, 6, 1);
    39. //显示一把邻结矩阵
    40. graph.showGraph();
    41. //测试一把,我们的dfs遍历是否ok
    42. System.out.println("深度遍历");
    43. graph.dfs(); // A->B->C->D->E [1->2->4->8->5->3->6->7]
    44. // System.out.println();
    45. System.out.println("广度优先!");
    46. graph.bfs(); // A->B->C->D-E [1->2->3->4->5->6->7->8]
    47. }
    48. //构造器
    49. public Graph(int n) {
    50. //初始化矩阵和vertexList
    51. edges = new int[n][n];
    52. vertexList = new ArrayList<String>(n);
    53. numOfEdges = 0;
    54. }
    55. //得到第一个邻接结点的下标 w
    56. /**
    57. *
    58. * @param index
    59. * @return 如果存在就返回对应的下标,否则返回-1
    60. */
    61. public int getFirstNeighbor(int index) {
    62. for(int j = 0; j < vertexList.size(); j++) {
    63. if(edges[index][j] > 0) {
    64. return j;
    65. }
    66. }
    67. return -1;
    68. }
    69. //根据前一个邻接结点的下标来获取下一个邻接结点
    70. public int getNextNeighbor(int v1, int v2) {
    71. for(int j = v2 + 1; j < vertexList.size(); j++) {
    72. if(edges[v1][j] > 0) {
    73. return j;
    74. }
    75. }
    76. return -1;
    77. }
    78. //深度优先遍历算法
    79. //i 第一次就是 0
    80. private void dfs(boolean[] isVisited, int i) {
    81. //首先我们访问该结点,输出
    82. System.out.print(getValueByIndex(i) + "->");
    83. //将结点设置为已经访问
    84. isVisited[i] = true;
    85. //查找结点i的第一个邻接结点w
    86. int w = getFirstNeighbor(i);
    87. while(w != -1) {//说明有
    88. if(!isVisited[w]) {
    89. dfs(isVisited, w);
    90. }
    91. //如果w结点已经被访问过
    92. w = getNextNeighbor(i, w);
    93. }
    94. }
    95. //对dfs 进行一个重载, 遍历我们所有的结点,并进行 dfs
    96. public void dfs() {
    97. isVisited = new boolean[vertexList.size()];
    98. //遍历所有的结点,进行dfs[回溯]
    99. for(int i = 0; i < getNumOfVertex(); i++) {
    100. if(!isVisited[i]) {
    101. dfs(isVisited, i);
    102. }
    103. }
    104. }
    105. //对一个结点进行广度优先遍历的方法
    106. private void bfs(boolean[] isVisited, int i) {
    107. int u ; // 表示队列的头结点对应下标
    108. int w ; // 邻接结点w
    109. //队列,记录结点访问的顺序
    110. LinkedList queue = new LinkedList();
    111. //访问结点,输出结点信息
    112. System.out.print(getValueByIndex(i) + "=>");
    113. //标记为已访问
    114. isVisited[i] = true;
    115. //将结点加入队列
    116. queue.addLast(i);
    117. while( !queue.isEmpty()) {
    118. //取出队列的头结点下标
    119. u = (Integer)queue.removeFirst();
    120. //得到第一个邻接结点的下标 w
    121. w = getFirstNeighbor(u);
    122. while(w != -1) {//找到
    123. //是否访问过
    124. if(!isVisited[w]) {
    125. System.out.print(getValueByIndex(w) + "=>");
    126. //标记已经访问
    127. isVisited[w] = true;
    128. //入队
    129. queue.addLast(w);
    130. }
    131. //以u为前驱点,找w后面的下一个邻结点
    132. w = getNextNeighbor(u, w); //体现出我们的广度优先
    133. }
    134. }
    135. }
    136. //遍历所有的结点,都进行广度优先搜索
    137. public void bfs() {
    138. isVisited = new boolean[vertexList.size()];
    139. for(int i = 0; i < getNumOfVertex(); i++) {
    140. if(!isVisited[i]) {
    141. bfs(isVisited, i);
    142. }
    143. }
    144. }
    145. //图中常用的方法
    146. //返回结点的个数
    147. public int getNumOfVertex() {
    148. return vertexList.size();
    149. }
    150. //显示图对应的矩阵
    151. public void showGraph() {
    152. for(int[] link : edges) {
    153. System.err.println(Arrays.toString(link));
    154. }
    155. }
    156. //得到边的数目
    157. public int getNumOfEdges() {
    158. return numOfEdges;
    159. }
    160. //返回结点i(下标)对应的数据 0->"A" 1->"B" 2->"C"
    161. public String getValueByIndex(int i) {
    162. return vertexList.get(i);
    163. }
    164. //返回v1和v2的权值
    165. public int getWeight(int v1, int v2) {
    166. return edges[v1][v2];
    167. }
    168. //插入结点
    169. public void insertVertex(String vertex) {
    170. vertexList.add(vertex);
    171. }
    172. //添加边
    173. /**
    174. *
    175. * @param v1 表示点的下标即使第几个顶点 "A"-"B" "A"->0 "B"->1
    176. * @param v2 第二个顶点对应的下标
    177. * @param weight 表示
    178. */
    179. public void insertEdge(int v1, int v2, int weight) {
    180. edges[v1][v2] = weight;
    181. edges[v2][v1] = weight;
    182. numOfEdges++;
    183. }
    184. }