Basic knowledge of graph structure

1. Related concepts

  • Graph G(V,E): A data structure that can represent a "many-to-many" relationship, consisting of a vertex set V and an edge set E;
  • Vertex:
  • Edge: a pair of points (v, w), v, w∈V, the edge is also called an arc;
  • Adjacency: point v, w adjacent, if and only if edge (v, w) ∈ E;
  • Path: consists of a vertex sequence v 1 , v 2 ,..., v n , the path length is n-1;
  • Directed graph: the edges are unidirectional, and the pairs of points are ordered;
  • Undirected graph: the edge is a bidirectional graph, and the point pairs are unordered;
  • Weighted graph: a graph in which different edges have different weights;
  • Connected: An undirected graph is called connected if there is a path from one vertex to any other vertex;
  • Strong connectivity: There is a path from a vertex of a directed graph to any other vertex;
  • Weakly connected: the directed graph itself is not strongly connected, but the undirected graph whose edges do not consider the direction is connected;
  • Complete graph: there is an edge between every pair of vertices;

2. Representation of graphs

  • Adjacency matrix : implemented using a two-dimensional array . Each element in the array indicates whether there is an edge between two vertices in the graph, or indicates the weight of the edge. It is suitable for dense graphs . For sparse graphs, this representation method is too wasteful of space;

insert image description here

package com.northsmile.graph;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * Author:NorthSmile
 * Create:2023/4/18 9:17
 * 使用邻接矩阵表示图(无向图)
 */
public class Graph {
    
    
    // 存储边及其权值
    int[][] edges;
    // 存储顶点
    ArrayList<String> vertexes;
    // 记录边的数目
    int edgeNums;

    public Graph(int n){
    
    
        edges=new int[n][n];
        vertexes=new ArrayList<>(n);
        edgeNums=0;
    }

    /**
     * 插入顶点
     * @param vertex
     */
    public void insertVertex(String vertex){
    
    
        vertexes.add(vertex);
    }

    /**
     * 插入边
     * @param v1 边的一个顶点对应下标
     * @param v2 边的另一个顶点对应下标
     * @param w 边对应权值,默认为1
     */
    public void insertEdge(int v1,int v2,int w){
    
    
        edges[v1][v2]=w;
        edges[v2][v1]=w;
        edgeNums++;
    }

    /**
     * 获取顶点数量
     * @return
     */
    public int getVertexesNum(){
    
    
        return vertexes.size();
    }

    /**
     * 获取边的数目
     * @return
     */
    public int getEdgesNum(){
    
    
        return edgeNums;
    }

    /**
     * 获取指定下标对应的顶点的值
     * @param v
     * @return
     */
    public String getValByIndex(int v){
    
    
        return vertexes.get(v);
    }

    /**
     * 获取指定边的权值
     * @param v1
     * @param v2
     * @return
     */
    public int getWeightOfEdge(int v1,int v2){
    
    
        return edges[v1][v2];
    }

    /**
     * 显示表示图的邻接矩阵
     */
    public void showGraph(){
    
    
        for (int[] edge:edges){
    
    
            System.out.println(Arrays.toString(edge));
        }
    }
}

package com.northsmile.graph;

/**
 * Author:NorthSmile
 * Create:2023/4/18 9:18
 */
public class GraphDemo {
    
    
    public static void main(String[] args) {
    
    
        int n=5;
        String[] vertexes={
    
    "A","B","C","D","E"};
        Graph graph = new Graph(n);

        // 插入顶点
        for (String vertex:vertexes){
    
    
            graph.insertVertex(vertex);
        }
        // 插入边
        graph.insertEdge(0,1,1);
        graph.insertEdge(0,2,1);
        graph.insertEdge(1,2,1);
        graph.insertEdge(1,3,1);
        graph.insertEdge(1,4,1);
        graph.showGraph();
    }
}
  • Adjacency list : implemented by array + linked list , suitable for sparse graph representation, is the standard representation method of graphs , for each vertex, store all its adjacency points in a table;
    insert image description here
package com.northsmile.graph;

import java.util.ArrayList;
import java.util.HashMap;

/**
 * Author:NorthSmile
 * Create:2023/4/18 11:12
 * 使用邻接表表示图(有向图)
 */
public class GraphByAdjacenceList {
    
    
    // 邻接表
    HashMap<String,Vertex> list;
    int vertexNums;
    int edgeNums;

    public GraphByAdjacenceList(int n){
    
    
        list=new HashMap<>();
        vertexNums=n;
        edgeNums=0;
    }

    /**
     * 插入顶点
     * @param vertex
     */
    public void insertVertex(String vertex){
    
    
        list.put(vertex,new Vertex(vertexNums));
    }

    /**
     * 插入边
     * @param v 顶点
     * @param w 邻接点
     */
    public void insertEdge(String v,String w){
    
    
        Vertex vertex = list.get(v);
        vertex.table.add(w);
        edgeNums++;
    }

    /**
     * 获取顶点数量
     * @return
     */
    public int getVertexesNum(){
    
    
        return list.size();
    }

    /**
     * 获取边的数目
     * @return
     */
    public int getEdgesNum(){
    
    
        return edgeNums;
    }

    /**
     * 显示表示图的邻接表
     */
    public void showGraph(){
    
    
        for (String vertex:list.keySet()){
    
    
            System.out.println(vertex+":"+list.get(vertex).table);
        }
    }

    /**
     * 顶点类
     */
    class Vertex{
    
    
        ArrayList<String> table;

        public Vertex(int n){
    
    
            table=new ArrayList<>(n/2);
        }
    }
}

package com.northsmile.graph;

/**
 * Author:NorthSmile
 * Create:2023/4/18 9:18
 */
public class GraphDemo {
    
    
    public static void main(String[] args) {
    
    
        // 2.邻接表
        int n=5;
        String[] vertexes={
    
    "A","B","C","D","E"};
        GraphByAdjacenceList graph = new GraphByAdjacenceList(n);

        // 插入顶点
        for (String vertex:vertexes){
    
    
            graph.insertVertex(vertex);
        }
        // 插入边
        graph.insertEdge("A","B");
        graph.insertEdge("A","C");
        graph.insertEdge("B","C");
        graph.insertEdge("B","D");
        graph.insertEdge("B","E");
        graph.showGraph();
    }
}

3. Graph traversal

insert image description here

3.1 Depth-first traversal (DFS)

  • Similar to the pre-order traversal of a tree, first visit the current vertex, and then use its adjacent points as the new starting point to perform depth-first traversal;
  • Unlike tree traversal, when the graph is traversed in depth first, the adjacent points of the current vertex may have been visited, so there is no need to visit again;
  • In order to realize the unique traversal of vertices, a tag array needs to be provided during code implementation, indicating whether the corresponding vertices have been visited;
  • Code implementation proceeds recursively;
    insert image description here
    insert image description here
    /**
     * 深度优先遍历:类似树的先序遍历
     * @param v 以当前点开始遍历
     * @param visited 标记节点是否访问过
     */
    public void dfs(int v,boolean[] visited){
    
    
        System.out.print(vertexes.get(v)+"->");
        // 遍历当前顶点的邻接点
        for (int i=0;i<vertexes.size();i++){
    
    
            // 说明v、i之间存在边
            if (edges[v][i]!=0&&!visited[i]){
    
    
                visited[i]=true;
                dfs(i,visited);
            }
        }
    }

    public void dfs(){
    
    
        // 标记顶点是否已经访问过
        boolean[] visited=new boolean[vertexes.size()];
        // 以每个顶点开始进行DFS,实现图的完整遍历
        for (int i=0;i<vertexes.size();i++){
    
    
            if (!visited[i]){
    
    
                visited[i]=true;
                dfs(i,visited);
            }
        }
    }

3.2 Breadth-first traversal (BFS)

  • Similar to tree-level traversal, first visit the current vertex, then visit its adjacent points in turn, and then continue breadth-first traversal with their adjacent points as the new starting point;
  • Unlike tree traversal, when the graph is traversed in depth first, the adjacent points of the current vertex may have been visited, so there is no need to visit again;
  • In order to realize the unique traversal of vertices, a tag array needs to be provided during code implementation, indicating whether the corresponding vertices have been visited;
  • The code is implemented by means of queues;
    insert image description here
    /**
     * 广度优先遍历:类似树的层次遍历
     * @param v 以当前点开始遍历
     * @param visited 标记节点是否访问过
     */
    public void bfs(int v,boolean[] visited){
    
    
        ArrayDeque<Integer> queue=new ArrayDeque<>();
        queue.offer(v);
        visited[v]=true;

        while (!queue.isEmpty()){
    
    
            Integer cur = queue.poll();
            System.out.print(vertexes.get(cur)+"->");
            // 遍历当前顶点的邻接点
            for (int i=0;i<vertexes.size();i++){
    
    
                // 说明v、i之间存在边
                if (edges[cur][i]!=0&&!visited[i]){
    
    
                    visited[i]=true;
                    queue.offer(i);
                }
            }
        }
    }

    public void bfs(){
    
    
        // 标记顶点是否已经访问过
        boolean[] visited=new boolean[vertexes.size()];
        // 以每个顶点开始进行BFS,实现图的完整遍历
        for (int i=0;i<vertexes.size();i++){
    
    
            if (!visited[i]){
    
    
                bfs(i,visited);
            }
        }
    }

Source: Shang Silicon Valley

Guess you like

Origin blog.csdn.net/qq_43665602/article/details/130208846