图是一种数据结构;
邻接表相较于邻接矩阵,减少了存储空间;
图的深度优先遍历(DFS)
图的广度优先遍历(BFS)
代码:
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.LinkedList;
-
- public class Graph {
- public static void main(String[] args) {
-
- int n = 8; // 节点的个数
- String[] vertexs = {"1", "2", "3", "4", "5", "6", "7", "8"};
- Graph graph = new Graph(n);
- // 添加顶点
- for (String VertexValue : vertexs) {
- graph.insertVertex(VertexValue);
- }
- graph.insertEdge(0, 1, 1);
- graph.insertEdge(0, 2, 1);
- graph.insertEdge(1, 3, 1);
- graph.insertEdge(1, 4, 1);
- graph.insertEdge(2, 5, 1);
- graph.insertEdge(2, 6, 1);
- graph.insertEdge(3, 7, 1);
- graph.insertEdge(4, 7, 1);
- graph.insertEdge(5, 6, 1);
- // 展示邻接矩阵
- graph.showGraph();
- graph.dfs();
- // graph.bfs();
- }
-
- private ArrayList
vertexList; //存储顶点的集合 - private int[][] edges; // 存储图的邻接矩阵
- private int numOfEdges; // 边的数量
- private boolean isVisited[]; // 是否被访问
-
- public Graph(int n) {
- edges = new int[n][n];
- vertexList = new ArrayList<>(n);
- numOfEdges = 0;
- isVisited = new boolean[n];
- }
-
- /**
- * 得到第一个邻接节点的下标
- *
- * @param index
- * @return
- */
- public int getFirstNeighbor(int index) {
- for (int j = 0; j < vertexList.size(); j++) {
- if (edges[index][j] > 0) {
- return j;
- }
- }
- return -1;
- }
-
- /**
- * 根据前一个邻接节点的下标来获取下一个邻接节点的下标
- *
- * @param v1
- * @param v2
- * @return
- */
- public int getNextNeighbor(int v1, int v2) {
- for (int j = v2 + 1; j < vertexList.size(); j++) {
- if (edges[v1][j] > 0) {
- return j;
- }
- }
- return -1;
- }
-
-
- /**
- * 深度优先遍历算法
- */
- public void dfs() {
- isVisited = new boolean[isVisited.length];
- for (int i = 0; i < getNumOfEdges(); i++) { // 节点个数5
- if (!isVisited[i]) {
- dfs(isVisited, i);
- }
- }
- }
-
- private void dfs(boolean[] isVisited, int i) {
- System.out.print(getValByIndex(i) + "->");
- // 将该节点设置为已访问
- isVisited[i] = true;
- // 查找节点i的第一个邻接节点
- int w = getFirstNeighbor(i);
- while (w != -1) {
- // 没有访问过
- if (!isVisited[w]) {
- dfs(isVisited, w);
- }
- // 邻接节点已经被访问过
- w = getNextNeighbor(i, w);
- }
- }
-
- /**
- * 遍历所有的节点,都进行广度优先搜索
- */
- public void bfs() {
- isVisited = new boolean[isVisited.length];
- for (int i = 0; i < getNumOfEdges(); i++) {
- if (!isVisited[i]) {
- bfs(isVisited, i);
- }
- }
- }
-
- /**
- * 对一个节点进行广度优先遍历的方法
- *
- * @param isVisited
- * @param i
- */
- private void bfs(boolean[] isVisited, int i) {
- int u; // 表示队列头节点对应的下标
- int w; // 邻接节点的下标
- // 队列,记录节点访问的顺序
- LinkedList
queue = new LinkedList<>(); - // 访问节点
- System.out.print(getValByIndex(i) + "=>");
- // 标记为已访问
- isVisited[i] = true;
- // 将节点加入队列
- queue.addLast(i);
- while (!queue.isEmpty()) {
- // 取出队列的头节点下标
- u = (Integer) queue.removeFirst();
- // 得到第一个邻接点的下标
- w = getFirstNeighbor(u);
- while (w != -1) {
- if (!isVisited[w]) {
- System.out.print(getValByIndex(w) + "=>");
- // 标记为已访问
- isVisited[w] = true;
- // 入队
- queue.addLast(w);
- }
- // 以u为前驱点,找w后面的邻接点
- w = getNextNeighbor(u, w);
- }
- }
- }
-
- /**
- * 添加边
- *
- * @param v1 表示第一个顶点的下标
- * @param v2 表示第二个顶点的下标
- * @param weight 权值
- */
- public void insertEdge(int v1, int v2, int weight) {
- edges[v1][v2] = weight;
- edges[v2][v1] = weight; // 无向图
- numOfEdges++;
- }
-
- /**
- * 添加节点
- *
- * @param vertex
- */
- public void insertVertex(String vertex) {
- vertexList.add(vertex);
- }
-
- /**
- * 返回节点的个数
- *
- * @return
- */
- public int getNumOfEdges() {
- return vertexList.size();
- }
-
- /**
- * 返回节点i(下标)对应的数据
- *
- * @param i
- * @return
- */
- public String getValByIndex(int i) {
- return vertexList.get(i);
- }
-
- /**
- * 返回v1和v2的权值
- *
- * @param v1
- * @param v2
- * @return
- */
- public int getWeight(int v1, int v2) {
- return edges[v1][v2];
- }
-
- /**
- * 显示图对应的矩阵
- */
- public void showGraph() {
- for (int[] edge : edges) {
- System.out.println(Arrays.toString(edge));
- }
- }
- }