[] Data structure - Figure in the end is what?

Do not you think, I think I want to, I said Figure it is not a thing. - Ming made it clear.

Why chart

Used to represent many relationship.

Limited to a linear form immediate predecessor and successor in a direct relationship

The tree can have only one parent is a direct precursor

basic concept

Side: two connection nodes

Vertex (vertex): data elements, a vertex may have zero or more adjacent elements.

Path: for example, there is a path from D-> C of

1)D->B->C

2)D->A->B->C

classification

Undirected graphs: As shown above, a non-directional connections between vertices. For example AB, i.e. may be a A-> B may B-> A.

Digraph: direction between the connected vertices, for example AB,

Only A-> B is not B-> A

Weighted graph: This chart with weights, also known as network edge

Representation

Or also storage structure

FIG representation of two ways: a two-dimensional array representation (the adjacency matrix); represents a list (the adjacency list).

Adjacency matrix

We use two arrays to represent the map:

One-dimensional array used to store the drawing vertex information

Two-dimensional array to store the deposit of the side information

All seeking neighbor vertex vi is the matrix element in row i and scanned again, arr[i][j]as is the adjacent point 1.

Adjacency matrix is ​​a matrix showing the relationship between the pattern of adjacent vertices for the vertices of the n FIG., The matrix is ​​a row and col. 1 .... n represent the point.

The following is an example undirected graph, observed:

Adjacency matrix is ​​a symmetric matrix

Main diagonal is 0, there is no vertex to the edge itself;

Adjacency list

Only concerned about the presence of edges.

Because the adjacency matrix are required to allocate space for each side of n vertices, there are many sides are not present, will cause some loss of space.

Achieve adjacency list only concern exists side, we do not care about non-existent side. Thus there is no wasted space, and an array of adjacent table lists the composition.

Create a chart

FIG code implements the following structure

    A   B   C   D   E
A   0   1   1   0   0
B   1   0   1   1   1
C   1   1   0   0   0
D   0   1   0   0   0 
E   0   1   0   0   0
//说明
//(1) 1 表示能够直接连接
//(2) 0 表示不能直接连接

Analysis of ideas:

We need two arrays

String type is used to store the vertex ArrayList

Two-dimensional array to store the information side

Common methods:

  1. Insert Vertex
  2. Insert edge
  3. Returns the number of nodes
  4. The number of edges obtained in each insertion edge on a cumulative
  5. A matrix display corresponding to FIG.
  6. Back node i (subscript) corresponding to data 0 -> "A" 1 -> "B" 2 -> "C"
  7. Return v1 and v2 weights, which weights the presence of the array.

Code

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

/**
 * @ClassName: Demo20_Graph
 * @author: benjamin
 * @version: 1.0
 * @description: TODO
 * @createTime: 2019/08/26/11:20
 */

public class Demo20_Graph {

  // 用于存储顶点的集合
  private ArrayList<String> vertexList;
  // 存储边的信息的二维数组
  private int[][] edges;
  // 记录边的数目
  private int numOfEdges;
  // 定义数组boolean[],记录某个结点是否被访问

  public static void main(String[] args) {
    Demo20_Graph graph = new Demo20_Graph(5);

    // 插入顶点
    String vertexs[] = {"A","B","C","D","E","F"};
    for(String vertex:vertexs){
        graph.insertVertex(vertex);
    }
    // 添加边
    // A-B A-C B-C B-D B-E
    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();
  }

  // 构造器,初始化矩阵和顶点集合
  Demo20_Graph(int n) {
    // 集合长度为n
    vertexList = new ArrayList<String>(n);
    // 邻接矩阵为n*n
    edges = new int[n][n];
    numOfEdges = 0;
  }

  //常用的方法
  //返回结点的个数
  public int getNumOfVertex() {
    return vertexList.size();
  }

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

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

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

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

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

  /**
   * 添加边
   *
   * @param v1 表示点的下标即使第几个顶点  "A"-"B" "A"->0 "B"->1
   * @param v2 第二个顶点对应的下标
   * @param weight 表示权,1或者0
   */
  public void insertEdge(int v1, int v2, int weight) {
    edges[v1][v2] = weight;
    edges[v2][v1] = weight;
    numOfEdges++;
  }

}

Output:

[0, 1, 1, 0, 0]
[1, 0, 1, 1, 1]
[1, 1, 0, 0, 0]
[0, 1, 0, 0, 0]
[0, 1, 0, 0, 0]

Traversing Graph

I.e., node access point. A chart there are so multiple nodes, how to traverse these nodes requires a specific strategy, there are two access policies:

  • Depth-first traversal
  • Breadth-first traversal

After selecting a former versed in the art, and then back to a study carried out in the field;

The latter, like entrepreneurship, starting from a known, already know something from the gradual re-excavated portion of interest;

Depth-first traversal (DFS)

The basic idea

Depth-first search map (Depth First Search)

From the initial access node, the initial access node may have multiple adjacent node, depth-first traversal strategy is to first visit the first adjacent node, and then to the adjacent node is accessed as an initial node access its first adjacent node, can be understood: first, every time access the first adjacent node of the current node after the completion of the current access node.

We can see that this strategy is a priority access to vertical excavation depth, depth-first search is a recursive process

DFS step how to achieve the figure above it?

A node as an initial, starting from A, labeled A first visited,

A first adjacent node B is present, B and has not been visited, now as the initial node B

Starting from B, labeled B has access to, a first adjacent node B by the presence of C, C is not accessed but now as the initial node C

D C next node node does not exist, back B, the end of the next adjacent node E B of

Algorithm steps

  1. Initial access node v, and node v marked as visited.
  2. Find a node v in the first adjacent node w.
  3. If w is present, proceed to 4, if w is not present, the process returns to step 1, v from the next node to continue.
  4. If access is not w, w to the recursive depth-first traversal (i.e., the other as a w v, then step 123).
  5. Find w v adjacent node of the node the next adjacent node, go to step 3.

Code

  /**
   * 得到第一个邻接结点的下标 w
   *
   * @return 如果存在就返回对应的下标,否则返回-1
   */
  public int getFirstNeighbor(int index) {
    for (int j = 0; j < vertexList.size(); j++) {
      if (edges[index][j] > 0) {
        return j;
      }
    }
    return -1;
  }

  /**
   * @Description: 根据前一个邻接结点的下标来获取下一个邻接结点
   * @Param: [v1, v2]
   * @return: int
   * @Author: benjamin
   * @Date: 2019/8/26
   */
  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;
  }

  //深度优先遍历算法
  //i 第一次就是 0
  private void dfs(boolean[] isVisited, int i) {
    // 首先输出访问的结点
    System.out.print(getValueByIndex(i) + "->");
    // 将结点设置为已经访问
    isVisited[i] = true;
    // 查找结点i的第一个邻接结点w
    int w = getFirstNeighbor(i);
    // 只要w不为1,说明有
    while (w != -1){
      if(!isVisited[w]){
        dfs(isVisited,w);
      }
      // 如果该结点已经被访问过,则访问i的下下一个邻接结点
      w = getNextNeighbor(i,w);
    }
  }

  //对dfs 进行一个重载, 遍历我们所有的结点,并进行 dfs
  public void dfs() {
    isVisited = new boolean[vertexList.size()];
    //遍历所有的结点,长度为集合的长度,进行dfs[回溯]
    for(int i = 0; i < getNumOfVertex(); i++) {
      if(!isVisited[i]) {
        dfs(isVisited, i);
      }
    }

  }

Breadth-first traversal (BFS)

The basic idea

Breadth-first search graph (Broad First Search).

A process similar to the hierarchical search, using a breadth-first traversal needs to preserve the ordering queues visited node, so in this order adjacent node to access these nodes

Algorithm steps

  1. Initial access nodes labeled node v and v as visited.
  2. Node queues v
  3. When the queue is not empty, continue, otherwise the algorithm ends.
  4. A queue, to obtain HOL node u.
  5. Find a node u in the first adjacent node w.
  6. If the node u w adjacent node does not exist, go to step 3; Otherwise, the cycle following three steps:
    1. If the node w yet been accessed, the access node w and marked as visited.
    2. Node queues w
    3. Find the next adjacent node w to the node u w following the adjacent node, go to step 6.

Code

/**
* 得到第一个邻接结点的下标 w
*
* @return 如果存在就返回对应的下标,否则返回-1
*/
public int getFirstNeighbor(int index) {
for (int j = 0; j < vertexList.size(); j++) {
  if (edges[index][j] > 0) {
    return j;
  }
}
return -1;
}

/**
* @Description: 根据前一个邻接结点的下标来获取下一个邻接结点
* @Param: [v1, v2]
* @return: int
* @Author: benjamin
* @Date: 2019/8/26
*/
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;
}
//对一个结点进行广度优先遍历的方法
private void bfs(boolean[] isVisited, int i) {
int u ; // 表示队列的头结点对应下标
int w ; // 邻接结点w
//队列,记录结点访问的顺序
LinkedList queue = new LinkedList();
//访问结点,输出结点信息
System.out.print(getValueByIndex(i) + "=>");
//标记为已访问
isVisited[i] = true;
//将结点加入队列
queue.addLast(i);

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

//遍历所有的结点,都进行广度优先搜索
public void bfs() {
isVisited = new boolean[vertexList.size()];// 清空标志位
for (int j = 0; j < vertexList.size(); j++) {
if (!isVisited[j]) {
bfs(isVisited, j);
}
}
}

Guess you like

Origin www.cnblogs.com/benjieqiang/p/11414409.html