1、基本介绍
深度优先遍历
步骤:
广度优先遍历
步骤:
2、应用实例
package graph;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class GraphTraverse {
public static void main(String[] args) {
String[] vertexs = {"A","B","C","D","E"};
Graph graph = new Graph(vertexs.length);
// 插入节点
for (String vertex : vertexs) {
graph.insertVertex(vertex);
}
// 插入边
graph.insertEdge(0, 1, 1);
graph.insertEdge(0, 2, 1);
graph.insertEdge(1, 0, 1);
graph.insertEdge(1, 2, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 4, 1);
graph.insertEdge(2, 0, 1);
graph.insertEdge(2, 1, 1);
graph.insertEdge(3, 1, 1);
graph.insertEdge(4, 1, 1);
System.out.println("图的顶点个数:" + graph.getNumOfVertex());
System.out.println("图的边的条数:" + graph.getNumOfEdges());
graph.showGraph(); // 打印矩阵(图)
// 深度优先搜索
System.out.print("深度优先搜索:");
graph.dfs(0);
// 广度优先搜索
System.out.print("\n广度优先搜索:");
graph.bfs(1);
}
}
class Graph {
public List<String> vertexLists; // 存储顶点的集合
public int[][] edges; // 存储边的二维数组
public int numOfVertex; // 顶点的个数
public int numOfEdges; // 边的条数
public boolean[] isVisited; // 记录该节点是否被访问过
public Graph (int numOfVertex) {
vertexLists = new ArrayList<>(numOfVertex);
edges = new int[numOfVertex][numOfVertex];
this.numOfVertex = numOfVertex;
this.numOfEdges = 0;
isVisited = new boolean[numOfVertex];
}
// 插入顶点
public void insertVertex(String vertex) {
vertexLists.add(vertex);
}
// 插入边
/*
v1:第一个顶点的下标
v2:第二个顶点的下标
w:权值,默认为1,表示这两个顶点有边
*/
public void insertEdge(int v1, int v2, int w) {
edges[v1][v2] = w;
edges[v2][v1] = w;
this.numOfEdges++;
}
// 打印图
public void showGraph() {
for (int[] temp : edges) {
System.out.println(Arrays.toString(temp));
}
System.out.println();
}
// 返回该图的顶点个数
public int getNumOfVertex() {
return this.numOfVertex;
}
// 返回该图的边的条数
public int getNumOfEdges() {
return (this.numOfEdges >> 1);
}
// 查找当前节点的下一个邻接点
// @返回对应节点的下标
public int getFirstNeighbor(int index) {
for (int i = 0; i < vertexLists.size(); i++) {
if (edges[index][i] > 0) { // 大于0,表示有边
return i;
}
}
return -1;
}
// 查找当前节点的邻接点的下一个邻接点
// @返回对应节点的下标
public int getNextNeighbor(int index, int v1) {
for (int i = v1 + 1; i < vertexLists.size(); i++) {
if (edges[index][i] > 0) {
return i;
}
}
return -1;
}
// 深度优先搜索
public void dfs(int v) {
// 输出当前节点
System.out.print(vertexLists.get(v) + " ");
// 标记当前节点为已访问节点
isVisited[v] = true;
// 查找当前节点的第一个邻接点
int w = getFirstNeighbor(v);
// 判断邻接点是否存在
while (w != -1) {
// 判断该邻接点是否已访问过
if (!isVisited[w]) {
dfs(w);
}
// 如果该邻接点已访问过,则找该邻接点的下一个邻接点
w = getNextNeighbor(v, w);
}
}
// 广度优先搜索
public void bfs(int v) {
// 用于存放节点
List queue = new LinkedList();
boolean[] isVisited = new boolean[this.numOfVertex]; // 不能用原有的isVisited数组,因为dfs时已被修改
// 输出当前节点
System.out.print(vertexLists.get(v) + " ");
// 标记当前节点为访问节点
isVisited[v] = true;
// 将当前节点入队
queue.add(v);
while(queue.size() > 0) {
// 取出队首节点
int u = (Integer) queue.remove(0);
// 获取该节点的第一个邻接点
int w = getFirstNeighbor(u);
// 判断该邻接点是否存在
while (w != -1) {
// 判断该邻接点是否被访问过
if (!isVisited[w]) {
// 输出当前节点
System.out.print(vertexLists.get(w) + " ");
// 将该邻接点标记为已访问
isVisited[w] = true;
// 将该邻接点入队
queue.add(w);
}
// 查找当前节点的下一个邻接点
w = getNextNeighbor(u, w);
}
}
}
}