1. package com.atguigu.graph;
    2. import java.util.ArrayList;
    3. import java.util.Arrays;
    4. /**
    5. * 图的简单实现
    6. *
    7. * @author Dxkstart
    8. * @create 2022-04-11-16:18
    9. */
    10. public class Graph {
    11. private ArrayList<String> varTextList; // 存储顶点
    12. private int[][] edges; // 存储图对应的邻接矩阵
    13. private int numOfEdges; // 表示边的个数
    14. private boolean[] isVisited; // 记录某个节点是否被访问
    15. public static void main(String[] args) {
    16. int n = 5;// 节点的个数
    17. String VarTexValue[] = {"A", "B", "C", "D", "E"};
    18. // 创建图对象
    19. Graph graph = new Graph(n);
    20. // 添加
    21. for (String str : VarTexValue) {
    22. graph.add(str);
    23. }
    24. // 添加边 A-B A-C B-C B-D B-E
    25. graph.addEdge(0, 1, 1); // A-B
    26. graph.addEdge(0, 2, 1); // A-C
    27. graph.addEdge(1, 2, 1); // B-C
    28. graph.addEdge(1, 3, 1); // B-D
    29. graph.addEdge(1, 4, 1); // B-E
    30. // 显示图的矩阵
    31. graph.showGraph();
    32. // 测试深度优先遍历
    33. graph.dfs();
    34. }
    35. // 构造器
    36. public Graph(int n) {
    37. // 初始化矩阵和varTextList
    38. edges = new int[n][n];
    39. varTextList = new ArrayList<String>(n);
    40. numOfEdges = 0;
    41. isVisited = new boolean[n];
    42. }
    43. // 插入节点
    44. public void add(String varText) {
    45. varTextList.add(varText);
    46. }
    47. // 添加边
    48. /**
    49. * @param v1 表示点的下标
    50. * @param v2 表示第二个顶点对应的下标
    51. * @param weight 表示边的权值
    52. */
    53. public void addEdge(int v1, int v2, int weight) {
    54. edges[v1][v2] = weight;
    55. edges[v2][v1] = weight;
    56. numOfEdges++;
    57. }
    58. // 返回节点的个数
    59. public int getNumOfVarText() {
    60. return varTextList.size();
    61. }
    62. // 返回边的数目
    63. public int getNumOfEdges() {
    64. return numOfEdges;
    65. }
    66. // 返回节点i(下标) 对应的数据
    67. public String getValueByIndex(int i) {
    68. return varTextList.get(i);
    69. }
    70. // 返回v1和v2的权值
    71. public int getWeight(int v1, int v2) {
    72. return edges[v1][v2];
    73. }
    74. // 显示图对应的矩阵
    75. public void showGraph() {
    76. for (int[] link : edges) {
    77. System.err.println(Arrays.toString(link));
    78. }
    79. }
    80. // 得到当前节点的第一个邻接节点的下标
    81. /**
    82. * @param index 当前节点的下标
    83. * @return 如果存在就返回下标,否则返回-1
    84. */
    85. public int getFirstNeighbor(int index) {
    86. for (int i = 0; i < varTextList.size(); i++) {
    87. if (edges[index][i] > 0) {
    88. return i;
    89. }
    90. }
    91. return -1;
    92. }
    93. // 根据当前节点的下标获取下一个节点的下标
    94. // v1,v2是当前节点的行和列下标
    95. public int getNextNeighbor(int v1, int v2) {
    96. for (int i = v2 + 1; i < varTextList.size(); i++) {
    97. if (edges[v1][i] > 0) {
    98. return i;
    99. }
    100. }
    101. return -1;
    102. }
    103. // 深度优先遍历算法
    104. public void dfs(boolean[] isVisited , int i) {
    105. // 先访问当前节点
    106. System.out.print(getValueByIndex(i) + " -> ");
    107. // 将当前节点置为已访问
    108. isVisited[i] = true;
    109. // 查找当前节点的第一个邻接节点
    110. int w = getFirstNeighbor(i);
    111. while (w != -1) {
    112. if (!isVisited[w]) {
    113. dfs(isVisited,w);
    114. }
    115. // 如果w节点已经被访问过了
    116. w = getNextNeighbor(i,w);// 2 , 0
    117. }
    118. }
    119. // 对dfs进行重载,遍历所有的节点,并进行dfs
    120. public void dfs() {
    121. // 遍历所有的节点,进行dfs【回溯】
    122. for (int i = 0; i < getNumOfVarText(); i++) {
    123. if (!isVisited[i]) {
    124. dfs(isVisited,i);
    125. }
    126. }
    127. }
    128. }