java之图的遍历

  • 深度优先遍历
  • 广度优先遍历
  • 代码



深度优先遍历

  • 首先明确概念 遍历,就是把图中的每个结点都输出一遍
  • 数据结构是采用的二维数组形式,其主对角元素为零,为对称矩阵。
  • 若矩阵arr[i][j]为1,代表i结点与j结点相连,如果某一行,某一列全0,意味着该点不与其他点相连,独立于其他所有点之外。

明确了以上概念之后,就可以写代码了,深度优先就是从某一个点(orig)开始,以该结点为前驱,按照结点集合中的顺序开始查找前驱结点a(orig)的后继结点b。一旦找到b,就以b作为前驱结点a,找b的后继结点。这个过程用到了递归算法。一旦找到b,就以b作为a进行递归。

每次找到某结点的后继结点b,以该后继结点b作为前驱a继续查找的时候,是从最开始(orig)结点开始一直找到当前结点,遇到遍历过的节点就跳过,遇到没遍历的节点就进行递归。这一步必须结合二维数组来看,不然看不懂。

为了验证某结点是否被遍历过,要设置一个布尔类型数组,数组长度等于集合长度,数组每一个元素对应集合中某个结点是否被遍历。总之就是要有一个数组,与集合的各元素一一对应。

最后的结果是,如果一个结点集合C中每一个结点ci都与其他结点至少有一条边进行连接,那么无论从这个集合中哪一个位置开始遍历,都会把该结点集合中的所有结点都输出一遍;如果某结点独立于其他所有结点,即没有任何一条边与该结点进行连接,则该节点不能被输出。

深度优先体现在,从某个结点开始,一直找到从这个结点(orig)按照结点集合顺序进行查找的最深的一条路径

广度优先遍历

  • 与深度优先dfs类似,广度优先bfs多了一个队列,每遍历一个结点,就把该结点添加到队列。
  • bfs不用递归,需用到两个while循环,一旦队列为空,终止遍历。

深度优先一旦找到某结点a后继结点b,就会开始递归,把b作为a进行查找。但是广度优先会找到b后,接着找与a相连的c,一直把所有与a相连的结点输出完毕后,然后让队列弹出一个结点,以该结点开始进行查找,其查找方式和dfs一样,也是从orig节点开始遍历。

广度优先体现在从某个结点开始,把所有与该结点相连的结点输出,然后从队列弹出一个结点,重复以上步骤。

代码

package com.atguigu.graph;

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

public class Graph {
	private ArrayList<String> vertexList ;
	private int[][] edges;
	private int numEdges;
	private boolean[] isVisited;
	
	public static void main(String[] args) {
//		String[] str = {"A","B","C","D","E"};
//		int vertexNum = 5;
		String[] str = {"1", "2", "3", "4", "5", "6", "7", "8"};
		int vertexNum = str.length;
		
		Graph graph = new Graph(vertexNum);
		//因为main方法在对象内部,故不受private影响,但是这儿最好采用构造器方法
//		graph.vertexList = new ArrayList<String>();
//		graph.edges = new int[vertexNum][vertexNum];
		for(String tmp:str) {
			graph.insertVertex(tmp);
		}
		
//		graph.addEdge(0, 1, 1);
//		graph.addEdge(0, 2, 1);
//		graph.addEdge(1, 2, 1);
//		graph.addEdge(1, 3, 1);
//		graph.addEdge(1, 4, 1);
		
		graph.addEdge(0, 1, 1);
		graph.addEdge(0, 2, 1);
		graph.addEdge(1, 3, 1);
		graph.addEdge(1, 4, 1);
		graph.addEdge(3, 7, 1);
		graph.addEdge(4, 7, 1);
		graph.addEdge(2, 5, 1);
		graph.addEdge(2, 6, 1);
		graph.addEdge(5, 6, 1);
		
		graph.showGraph();
		System.out.println("深度优先");
		graph.dfs();
		System.out.println();
		System.out.println("广度优先");
		graph.bfs();
	}
	
	public int getFirstEdge(int n) {
		for(int i = 0;i < vertexList.size();i++) {
			if(edges[n][i] > 0)
				return i;
		}
		return -1;
	}
	
	public int getNextEdge(int i , int j) {
		for(int num = j+1;num < vertexList.size();num++) {
			if(edges[i][num] > 0)
				return num;
		}
		return -1;
	}
	
	public void dfs(boolean[] isVisited, int i) {

		System.out.print(vertexList.get(i)+"\t");
		isVisited[i] = true;
		int w = getFirstEdge(i);
		while(w != -1) {
			if(!isVisited[w])
				dfs(isVisited,w);
			w = getNextEdge(i, w);
		}
	}
	
	public void dfs() {
		isVisited = new boolean[vertexList.size()];
		for(int i = 0;i < vertexList.size();i++) {
			if(!isVisited[i])
				dfs(isVisited,i);
		}
	}
	
	public void bfs(boolean[] isVisited,int i) {
		int u;
		int w;
		System.out.print(vertexList.get(i)+"\t");
		isVisited[i] = true;
		LinkedList queue = new LinkedList();
		queue.addLast(i);
		while(!queue.isEmpty()) {
			u = (int)queue.removeFirst();
			w = getFirstEdge(u);
			while(w != -1) {
				if(!isVisited[w]) {
					System.out.print(vertexList.get(w)+"\t");
					isVisited[w] = true;
					queue.addLast(w);
				}
				w = getNextEdge(u, w);
			}
			
		}
	}
	
	public void bfs() {
		isVisited = new boolean[vertexList.size()];
		for(int i = 0;i<vertexList.size();i++) {
			if(!isVisited[i])
				bfs(isVisited,i);
		}
	}
	
	public Graph(int num) {
		vertexList = new ArrayList<String>();
		edges = new int[num][num];
	}
	
	public int getVertexNum() {
		return vertexList.size();
	}
	
	public int getEdgesNum() {
		return numEdges;
	}
	
	public int getWeight(int v1,int v2) {
		return edges[v1][v2];
	}
	
	public String getVertexValue(int index) {
		return vertexList.get(index);
	}
	
	public void showGraph() {
		for(int[] link:edges) {
			System.out.println(Arrays.toString(link));
		}
	}
	
	public void insertVertex(String vertex) {
		vertexList.add(vertex);
	}
	
	public void addEdge(int v1,int v2,int weight) {
		edges[v1][v2]=weight;
		edges[v2][v1]=weight;
		numEdges++;
	}
	
}

示例图

Java BFS 公式 java bfs和dfs_结点


图片选择尚硅谷

运行结果

[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]
深度优先
1 2 4 8 5 3 6 7
广度优先
1 2 3 4 5 6 7 8