[java]-Algorithms and Data Structures-Chapter 11-Graphs

1. Basic introduction

1) Why is there a picture

  1. Earlier we learned about linear tables and trees
  2. Linear tables are limited to a relationship between an immediate predecessor and an immediate successor
  3. A tree can only have one immediate predecessor, the parent node.
  4. When we need to represent many-to-many relationships, here we use graphs

2) Give an example

A graph is a data structure in which a node can have zero or more adjacent elements. A connection between two nodes is called a visit. A node may be called a point. As shown in the picture:

3) Common concepts

  1. Vertex

  2. edge

  3. path

  4. Undirected graph (below)
    insert image description here

  5. directed graph
    insert image description here

  6. weighted graph

insert image description here

4) Representation

There are two ways to represent graphs:

  • Two-dimensional array representation (adjacency matrix)

    The adjacency matrix is ​​a matrix that represents the adjacency relationship between vertices in a graph. For a graph with n vertices, the row and col of the matrix represent 1...n

insert image description here

  • Linked list representation (adjacency list)
    • The adjacency matrix needs to allocate n edge space for each vertex. In fact, many edges do not exist, which will cause a certain loss of space.
    • The implementation of the adjacency list only cares about the edges that exist, not the edges that do not exist. So there is no space wasted, the adjacency list consists of array + linked list

insert image description here

illustrate:

  1. The associated nodes of the node labeled 0 are 1 2 3 4
  2. The associated node of the node labeled 1 is 0 4
  3. The nodes associated with the node labeled 2 are 0 4 5

2. Getting Started Case

1) requirements

insert image description here

2) Code implementation

package A10_图;
/*
    Date:2022/5/19
    author: Blue Friday
    describe: //todo
*/

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

public class Graph {
    
    
    private ArrayList<String> vertexList; // 存储顶点集合

    private int[][] edges; // 存储图对应的邻接矩阵
    private int numOfEdges; // 表示边的数目

    public static void main(String[] args) {
    
    
        int n = 5;
        String VertexValue[] = {
    
    "A", "B", "C", "D", "E"};
        Graph graph = new Graph(n);
        for (String s : VertexValue) {
    
    
            graph.insertVertex(s);
        }
        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();
    }

    // 构造器
    public Graph(int n) {
    
    
        // 初始化 矩阵
        edges = new int[n][n];
        vertexList = new ArrayList<>(n);
        numOfEdges = 0;
    }

    // 插入结点
    public void insertVertex(String vertex) {
    
    
        vertexList.add(vertex);
    }

    // 添加边
    public void insertEdge(int v1, int v2, int weight) {
    
    
        // v1:点的下标
        // v2:第二个顶点的下标
        // weight:表示
        edges[v1][v2] = weight;
        edges[v2][v1] = weight;
        numOfEdges++;
    }

    // 图常用方法

    // 1. 返回节点个数
    public int getNumOfVertex() {
    
    
        return vertexList.size();
    }

    // 2. 得到边的数目
    public int getNumOfEdges() {
    
    
        return numOfEdges;
    }

    // 3. 返回节点 i 对应的数据 "0 -> A ; 1 -> B ; 2 -> C"
    public String getValueByIndex(int i) {
    
    
        return vertexList.get(i);
    }

    // 4. 返回 v1 v2 的权值
    public int getWeight(int v1, int v2) {
    
    
        return edges[v1][v2];
    }

    // 5. 显示图对应的矩阵
    public void showGraph() {
    
    
        for (int[] link : edges) {
    
    
            System.out.println(Arrays.toString(link));
        }
    }

}


3. Depth-first traversal

1) Introduction to graph traversal

The so-called graph traversal is the access to the nodes. There are so many nodes in a graph, how to traverse these nodes requires a specific strategy, generally there are two access strategies

  1. Depth-first traversal
  2. breadth first traversal

2) The basic idea of ​​depth-first traversal

Depth First Search of graphs.

  1. Depth-first traversal, starting from the initial access node, the initial access node may have multiple adjacent nodes, the strategy of depth-first traversal is to first visit the first adjacent node, and then use the visited adjacent node as the initial node, visit its first adjacent node,

    It can be understood like this: every time after visiting the current node, first visit the first adjacent node of the current node.

  2. We can see that such an access strategy is to dig deeper vertically instead of horizontally accessing all adjacent nodes of a node.

  3. Obviously, depth-first search is a recursive process

3) Depth-first traversal algorithm steps

  1. Visit the initial node v, and mark node v as visited
  2. Find the first adjacent node w of node v
  3. If w exists, continue to 4, if not, return to the first step, and continue from the next node of v
  4. If w has not been visited, perform depth-first traversal recursion on w (that is, treat w as another v, and then proceed to step 1 2 3 )
  5. Find the next adjacent node of the w adjacent node of node v, go to step 3

A→B→C

B→D

B→E

4) Code

    // ------深度遍历---------------------------------------------------------
    // 得到第一个邻接结点的下标w
    public int getFirstNeighbor(int index) {
    
    
        for (int i = 0; i < vertexList.size(); i++) {
    
    
            if (edges[index][i] > 0) {
    
     // 下一个邻结点存在
                return i;
            }
        }
        return -1;
    }

    // 根据前一个邻接结点的下标获取下一个邻接结点
    public int getNextNeighbor(int v1, int v2) {
    
    
        for (int i = v2 + 1; i < vertexList.size(); i++) {
    
    
            if (edges[v1][i] > 0) {
    
    
                return i;
            }
        }
        return -1;
    }

    // 深度优先遍历算法
    public void dfs(boolean[] isVisited, int i) {
    
    
        // 首先,访问该结点
        System.out.print(getValueByIndex(i) + " -> ");
        // 设置已经访问
        isVisited[i] = true;
        int w = getFirstNeighbor(i);
        while (w != -1) {
    
     // 说明有值
            if (!isVisited[w]) {
    
    
                dfs(isVisited, w);
            }
            // 如果 w结点被访问过
            w = getNextNeighbor(i, w);
        }
    }

    // 重载
    public void dfs() {
    
    
        // 遍历所有结点进行 dfs
        for (int i = 0; i < getNumOfEdges(); i++) {
    
    
            if (!isVisited[i]) {
    
    
                dfs(isVisited, i);
            }
        }

    }

4. Breadth-first traversal

1 Introduction

Graph Breadth First Search (Broad First Search). Similar to a hierarchical search process, breadth-first traversal needs to use a queue to keep the order of the visited nodes, so as to visit the adjacent nodes of these nodes in this order.

2) Algorithm steps

  1. Visit the initial node v and mark node v as visited
  2. Node v enqueues
  3. When the queue is not empty, continue to execute, otherwise the algorithm ends
  4. Get out of the queue and take out the queue head node U
  5. Find the first adjacent node w of node u
  6. If the adjacent node w of node u does not exist, then go to 3,; otherwise, perform the following three steps in a loop
    • If node w has not been visited, visit node w and mark it as visited
    • Node w enters the queue
    • Find the next adjacent node w after the adjacent node of node u, go to 6

3) Code

    // -------广度遍历-----------------------------------------------------------
    public void bfs(boolean[] isVisited, int i) {
    
    
        int u; // 表示队列的头节点对应下标
        int w; // 邻接结点w
        // 队列,记录结点访问顺序
        LinkedList<Integer> queue = new LinkedList<>();
        System.out.println(getValueByIndex(i) + " -> ");
        // 标记为已访问
        isVisited[i] = true;
        // 将节点加入队列
        queue.addLast(i);

        while (!queue.isEmpty()) {
    
    
            // 取出队列的头结点下标
            u = queue.removeFirst();
            // 得到第一个邻接结点的下标 w
            w = getFirstNeighbor(u);
            while (w != -1) {
    
     // 找到
                // 是否访问过
                if (!isVisited[w]) {
    
    
                    System.out.println(getValueByIndex(w) + " -> ");
                    // 标记
                    isVisited[w] = true;
                    queue.addLast(w);
                }
                // 以 u 为前驱点,找w后的邻接结点
                w = getNextNeighbor(u, w);
            }
        }
    }

    public void bfs() {
    
    
        for (int i = 0; i < getNumOfEdges(); i++) {
    
    
            if(!isVisited[i]){
    
    
                bfs(isVisited, i);
            }
        }
    }

5. Compare

[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (img-sLuAuFRU-1652950874607)(https://secure2.wostatic.cn/static/mBWR5FpbVbrNSUg85NSZ1S/image.png)]

        int n = 8;
        String VertexValue[] = {
    
    "1", "2", "3", "4", "5", "6", "7", "8"};

        Graph graph = new Graph(n);
        for (String s : VertexValue) {
    
    
            graph.insertVertex(s);
        }
        graph.insertEdge(0, 1, 1);
        graph.insertEdge(0, 2, 1);
        graph.insertEdge(1, 3, 1);
        graph.insertEdge(1, 4, 1);
        graph.insertEdge(3, 7, 1);
        graph.insertEdge(4, 7, 1);
        graph.insertEdge(2, 5, 1);
        graph.insertEdge(2, 6, 1);
        graph.insertEdge(5, 6, 1);

        graph.showGraph();
        System.out.println("-------dfs-------------");
        graph.dfs();
        System.out.println();
        System.out.println("-------d=bfs-------------");
        graph.bfs();

result

[0, 1, 1, 0, 0, 0, 0, 0]
[1, 0, 0, 1, 1, 0, 0, 0]
[1, 0, 0, 0, 0, 1, 1, 0]
[0, 1, 0, 0, 0, 0, 0, 1]
[0, 1, 0, 0, 0, 0, 0, 1]
[0, 0, 1, 0, 0, 0, 1, 0]
[0, 0, 1, 0, 0, 1, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0]
-------dfs-------------
1 -> 2 -> 4 -> 8 -> 5 -> 3 -> 6 -> 7 -> 
-------bfs-------------
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 ->

Guess you like

Origin blog.csdn.net/m0_56186460/article/details/124867053