Data structure------depth breadth first traversal

Figure

Why use graphs

The linear table is limited to the relationship between a direct predecessor and a direct successor. The
tree can only have one direct predecessor, which is the parent node.
When we need to express a many-to-many relationship, here we use a graph.

In other words, the graph can represent the relationship between many-to-many

A graph is a data structure in which a node can have zero or more adjacent elements . The connection between two nodes is called an edge . Nodes can also be called vertices.

Common concepts

1. The vertex is our node

2. Edge connection between our neighboring nodes

3. How many ways are there to connect between path nodes

4. Undirected graph

Insert picture description here

5. A directed graph has directions on the edges

6. Weighted graphs with valued graphs

Representation

1. Two-dimensional array representation adjacency matrix

2. The linked list represents the adjacency list

Insert picture description here

We found that many places are meaningless and waste space

Insert picture description here

Quick start

Insert picture description here

Code

package;

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 value : VertexValue){
    
    
			graph.insertVertex(value);
		}
		//添加边
		// 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();
	}
	
	//构造器
	public Graph(int n){
    
    
		//初始化矩阵和vertexList
		edges = new int[n][n];
		vertexList = new ArrayList<String>(n);
		numOfEdges = 0;
	}
	//插入节点
	public void insertVertex(String vertex){
    
    
		vertexList.add(vertex);
	}
	//添加边
	/**
	 * 
	 * @param v1	表示第一个顶点的下标即是第几个顶点
	 * @param v2	第一个顶点的下标
	 * @param weight	表示值是不是1即有没有连接起来
	 */
	public void insertEdge(int v1,int v2,int weight){
    
    
		edges[v1][v2] = weight;
		edges[v2][v1] = weight;
		numOfEdges++;
	}
	//返回节点的个数
	public int getNumOfVertex(){
    
    
		return vertexList.size();
	}
	//返回边的数目
	public int getNumOfEdges(){
    
    
		return numOfEdges;
	}
	//返回节点i对应的数据
	public String getValueByIndex(int i){
    
    
		return vertexList.get(i);
	}
	//返回v1和v2的权值
	public int getWeight(int v1,int v2){
    
    
		return edges[v1][v2];
	}
	//显示图对应的矩阵
	public void showGraph(){
    
    
		for (int[] link : edges) {
    
    
			System.err.println(Arrays.toString(link));
		}
	}
}

Depth-first traversal

Basic idea

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 this visited adjacent node as the initial A node , visiting its first adjacent node, can be understood as follows: every time after visiting the current node, first visit the first adjacent node of the current node .
We can see that such an access strategy prioritizes digging vertically, rather than horizontally accessing all adjacent nodes of one node.
Obviously, depth-first search is a recursive process

step

1. Visit the initial node v and mark that node v has been visited

2. Find the first adjacent node W of node V

3. If W exists, go to step 4, if w does not exist, go back to step 1, 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 123).

5. Find the next adjacent node of the W adjacent node of node v, and go to step 3

package;

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

public class Graph {
    
    
	private ArrayList<String> vertexList;   //存储顶点集合
	private int[][] edges; //存储图对应的邻接矩阵
	private int numOfEdges;  //表示边的数目
	//定义一个boolean[]  记录某个点是否被访问过
	private boolean[] isVisited;
	public static void main(String[] args) {
    
    
		int n = 5;   //节点的个数
		String VertexValue[] = {
    
    "A","B","C","D","E"};
		//创建图对象
		Graph graph = new Graph(n);
		//循环添加顶点
		for(String value : VertexValue){
    
    
			graph.insertVertex(value);
		}
		//添加边
		// 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();
		System.out.println("深度遍历");
		graph.dfs();
		
	}
	
	//构造器
	public Graph(int n){
    
    
		//初始化矩阵和vertexList
		edges = new int[n][n];
		vertexList = new ArrayList<String>(n);
		numOfEdges = 0;
		isVisited = new boolean[5];
	}
	//得到第一个邻接节点的下标
	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 j = v2+1;j<vertexList.size();j++){
    
    
			if(edges[v1][j] > 0){
    
    
				return j;
			}
		}
		return -1;
	}
	//深度优先遍历算法
	public void dfs(boolean[] isVisited,int i){
    
    
		//首先访问该节点
		System.out.println(getValueByIndex(i)+"->");
		//将该节点设置为已访问
		isVisited[i] = true;
		//查找节点i的邻接节点
		int w = getFirstNeighbor(i);
		while(w!=-1){
    
    //有邻接节点
			if(!isVisited[w]){
    
    
				dfs(isVisited,w);
			}
			//如果已经被访问过
			w = getNextNeighbor(i, w);
		}
	}
	//对dfs重载,遍历所有节点,并进行dfs
	public void dfs(){
    
    
		for(int i=0;i<getNumOfVertex();i++){
    
    
			if(!isVisited[i]){
    
    
				dfs(isVisited,i);
			}
		}
	}
	//插入节点
	public void insertVertex(String vertex){
    
    
		vertexList.add(vertex);
	}
	//添加边
	/**
	 * 
	 * @param v1	表示第一个顶点的下标即是第几个顶点
	 * @param v2	第一个顶点的下标
	 * @param weight	表示值是不是1即有没有连接起来
	 */
	public void insertEdge(int v1,int v2,int weight){
    
    
		edges[v1][v2] = weight;
		edges[v2][v1] = weight;
		numOfEdges++;
	}
	//返回节点的个数
	public int getNumOfVertex(){
    
    
		return vertexList.size();
	}
	//返回边的数目
	public int getNumOfEdges(){
    
    
		return numOfEdges;
	}
	//返回节点i对应的数据
	public String getValueByIndex(int i){
    
    
		return vertexList.get(i);
	}
	//返回v1和v2的权值
	public int getWeight(int v1,int v2){
    
    
		return edges[v1][v2];
	}
	//显示图对应的矩阵
	public void showGraph(){
    
    
		for (int[] link : edges) {
    
    
			System.err.println(Arrays.toString(link));
		}
	}
}

Breadth first traversal

Basic idea

Similar to a hierarchical search process, breadth-first traversal requires the use of a queue to maintain the order of the visited nodes, so that the adjacent nodes of these nodes can be visited in this order

step

  1. Visit the initial settlement and mark node v as visited.
  2. When the node enters the queue
    3, when the queue is not empty, continue to execute (the algorithm ends when the fragrance is incense).
  3. Get out of the queue and get the head node u.
  4. Find the second adjacent node w of node u.
  5. If the adjacent node w of the landing point u does not exist, go to step 3; otherwise, the following three steps are performed in a loop:
    6.1 If the node w has not been visited, then the node w is visited and marked as visited.
    6.2 Node w enters the queue
    6.3 Find the next adjacent node w following the adjacent node w of node u, and go to step 6.

Code

Just post our method code directly here

	//广度优先遍历
	private void bfs(boolean[] isVisited, int i){
    
    
		int u;   //表示队列头结点的下标
		int w;	 //邻接节点的下标
		//需要一个队列,记录节点访问的顺序
		LinkedList queue = new LinkedList();
		//访问节点,输出节点信息
		System.out.print(getValueByIndex(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(getValueByIndex(w)+"->");
					isVisited[w] = true;
					//入队
					queue.addLast(w);
				}
				//以u为前驱点,找w后面的下一个邻接节点
				w = getNextNeighbor(u, w);//体现出广度优先遍历	
			}
		}
	}
	//对所有节点进行广度优先搜索
	public void bfs(){
    
    
		for(int i=0;i<getNumOfVertex();i++){
    
    
			if(!isVisited[i]){
    
    
				bfs(isVisited, i);
			}
		}
	}
广度优先遍历
[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]
A->B->C->D->E->

The difference between the two traversal methods

Insert picture description here

Guess you like

Origin blog.csdn.net/qq_22155255/article/details/113858619