99 阅读2分钟

「这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战」。

图(Graph)

由顶点集合和边集组成。分为有向图无向图权重图

  1. 无向图:每个顶点和其他顶点无方向的连接。

  2. 有向图:每个顶点和其他顶点有方向的连接。

  3. 权重图:每条相连线存在各自的权重。

有向图的实现

截屏2022-02-21 下午8.48.24

可以利用邻接矩阵来实现。

n\m
0110
0011
0001
0000

矩阵中0表示n点到m点没有边,1表示n点到m点存在有向边。

也可以利用链表来实现

截屏2022-02-21 下午9.01.30

代码实现(链表)

public class ListGraph{
  
  ArraryList<ArraryList<Integer>>graphs;
  
  public ListGraph(int v){
    graphs = new ArrayList<>(v);
    for(int i = 0;i < V;i ++){
      graphs.add(new ArrayList<>());
    }
  }
  
  // 尾插法插入节点
  public void addEdge(int start,int end){
    graphs.get(start).add(end);
  }
  
  // 删除节点
  public void removeEdge(int start,int end){
    graphs.get(start).remove((Integer)end);
  }
  
}

图的遍历

4DDD88C2C08FE06DB902195661E25911

DFS(深度优先遍历)

  1. 假设初始状态所有的顶点都未被访问,然后从每一个顶点v出发,先访问该顶点
  2. 然后依次从他未访问的邻接点出发,深度优先遍历图,直到图中所有和v相通的顶点都被访问到。
  3. 遍历完后如果还有其他顶点未被访问到,则另选一个未被访问的顶点作为起始点。
  4. 重复上述过程,直到所有顶点都被访问完为止。
截屏2022-02-21 下午9.51.26
代码
/**图的实体类**/
public class ListGraph{

    ArrayList<ArrayList<Integer>>graphs;

    public ListGraph(int v){
        graphs = new ArrayList<>(v);
        for(int i = 0;i < v;i ++){
            graphs.add(new ArrayList<>());
        }
    }

    // 尾插法插入节点
    public void addEdge(int start,int end){
        graphs.get(start).add(end);
    }

    // 删除节点
    public void removeEdge(int start,int end){
        graphs.get(start).remove((Integer)end);
    }

}

/**实现类**/
class GraphTraversal{
    // 之前实现的图
    ListGraph graph;

    // 标记访问过的节点
    boolean[] visited;

    public GraphTraversal(ListGraph listGraph){
        this.graph = listGraph;
        visited = new boolean[listGraph.graphs.size()];
    }

    public void DFSTraversal(int v) {
        if (visited[v]) {
            return;
        }
        visited[v] = true;
        System.out.print(v + "->");
        Iterator<Integer> neighbors = graph.graphs.get(v).listIterator();
        while (neighbors.hasNext()) {
            int nextNode = neighbors.next();
            if (!visited[nextNode]) {
                DFSTraversal(nextNode);
            }
        }
    }
    public void DFS(){
        for(int i = 0; i < graph.graphs.size();i++){
            if(!visited[i]){
                DFSTraversal(i);
            }
        }
    }
}

BFS(广度优先遍历)

  1. 从图中的某一点出发,在访问了v之后依次访问v的各个没有访问到的邻接点。
  2. 然后分别从这些邻接点出发依次访问他们的邻接点,使得先被访问的邻接点先与后被访问顶点的邻接点被访问,直到图中所有已被访问的顶点的邻接点都被访问到。
  3. 如果此时图中尚有顶点未被访问,则需要另选一个未曾被访问到的顶点作为新的起始点,重复上述过程。

image-20220222195832585

代码

/**图的实体类**/
public class ListGraph{

    ArrayList<ArrayList<Integer>>graphs;

    public ListGraph(int v){
        graphs = new ArrayList<>(v);
        for(int i = 0;i < v;i ++){
            graphs.add(new ArrayList<>());
        }
    }

    // 尾插法插入节点
    public void addEdge(int start,int end){
        graphs.get(start).add(end);
    }

    // 删除节点
    public void removeEdge(int start,int end){
        graphs.get(start).remove((Integer)end);
    }

}

/**实现类**/
class GraphTraversal{
    /** 之前实现的图*/
    ListGraph graph;

    /** 标记访问过的节点*/
    boolean[] visited;

    public GraphTraversal(ListGraph listGraph){
        this.graph = listGraph;
        visited = new boolean[listGraph.graphs.size()];
    }


    public void BFSTraversal(int v){
        Deque<Integer>queue = new ArrayDeque<>();
        visited[v] = true;
        queue.offerFirst(v);
        while(queue.size() != 0){
            Integer cur = queue.pollFirst();
            System.out.println(cur+"->");
            ListIterator<Integer> neighbors = graph.graphs.get(cur).listIterator();
            int nextNode = neighbors.next();
            if(!visited[nextNode]){
                queue.offerLast(nextNode);
                visited[nextNode] = true;
            }
        }
    }
    public void BFS(){
        for (int i = 0; i < graph.graphs.size(); i++) {
            if (!visited[i]){
                BFSTraversal(i);
            }
        }
    }
}