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++;
}
}
示例图
图片选择尚硅谷
运行结果
[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