java实现图的深度优先搜索和广度优先搜索
深度优先搜索属于图算法的一种,英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次.
宽度优先搜索算法(又称广度优先搜索),其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
举例说明之:下图是一个无向图,如果我们从A点发起深度优先搜索(以下的访问次序并不是唯一的,第二个点既可以是B也可以是C,D),则我们可能得到如下的一个访问过程:A->B->E(没有路了!回溯到A)->C->F->H->G->D(没有路,最终回溯到A,A也没有未访问的相邻节点,本次搜索结束)
深度优先搜索的顺序是:A->B->E->C->F->H->G->D
广度优先搜索的顺序是:A->B->C->D->E->F->G->H
下面是java代码实现
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
public class Graph {
public int n ; //顶点的个数
public ArrayList<String> vertexList; //每个顶点的名称
public int[][] edges; //两个顶点是否有边相连
public int numEdge; //边的数目
public boolean[] isVisited; //每个结点是否被访问过
public static void main(String[] args) {
//添加顶点
Graph graph = new Graph(8);
String[] vertexs={"A","B","C","D","E","F","G","H"};
for (String vertex:vertexs){
graph.addVertex(vertex);
}
//添加边
graph.addEdge(0,1,1);
graph.addEdge(1,4,1);
graph.addEdge(0,2,1);
graph.addEdge(2,5,1);
graph.addEdge(5,7,1);
graph.addEdge(0,3,1);
graph.addEdge(3,6,1);
graph.addEdge(6,7,1);
//显示矩阵
graph.showEdges();
System.out.printf("\n深度优先遍历:");
graph.dfs();
// System.out.printf("\n广度优先遍历:");
// graph.bfs();
}
public Graph(int n) {
this.n = n;
vertexList=new ArrayList<>();
edges=new int[n][n];
isVisited= new boolean[n];
numEdge =0;
}
//添加顶点
public void addVertex(String vertex){
vertexList.add(vertex);
}
//添加边
/**
* 给两个已知的点添加边
* @param v1 第一个顶点(比如:‘A’->'0' 'B'->'1' )
* @param v2 第二个顶点
* @param weight 边的长度
*/
public void addEdge(int v1,int v2,int weight){
edges[v1][v2]=weight;
edges[v2][v1]=weight;
numEdge++;
}
//用矩阵遍历,所有的边
public void showEdges(){
for (int[] edge: edges){
System.out.println(Arrays.toString(edge));
}
}
//返回当前结点的第一个临界结点
public int getFirstNeighbour(int index){
for (int i=0;i<vertexList.size();i++){
if (edges[index][i]>0){
return i;
}
}
return -1;
}
//返回当前结点的下一个结点
public int getNextNeighbour(int v1,int v2){
for (int j=v2+1;j<vertexList.size();j++){
if (edges[v1][j] > 0) {
return j;
}
}
return -1;
}
//广度优先遍历
public void bfs(boolean[] isVisited,int i){
int u;//素表示队列头的第一个元
int w;
//用一个队列来进行保存访问过的
LinkedList<Integer> queue = new LinkedList<>();
//输出当前结点
System.out.printf(getValueByIndex(i)+"->");
//把当前结点标记为以访问
isVisited[i]=true;
//将该结点加入到队列中
queue.addLast(i);
//如果队列不为空
while (!queue.isEmpty()) {
//获取队列头部的第一个结点
u=queue.removeFirst();
//获取当前结点的第一个邻接点
w = getFirstNeighbour(u);
while (w != -1) {
//判断该结点是否访问过
if (!isVisited[w]) {
//如果没有访问过,就输出(这里是和深度优先搜索遍历不一样的地方)
System.out.printf(getValueByIndex(w) + "->");
isVisited[w] = true;
queue.addLast(w);
}
w = getNextNeighbour(u, w);
}
}
}
public void bfs(){
for (int i=0;i<getNumVertex();i++){
if (!isVisited[i]){
bfs(isVisited, i);
}
}
}
//深度优先遍历
public void dfs(boolean[] isVisited,int i){
//输出当前结点
System.out.printf(getValueByIndex(i)+"->");
//把当前结点的 值设置成true
isVisited[i]=true;
//获取当前结点的第一个邻接点
int w = getFirstNeighbour(i);
while (w!=-1){
if (!isVisited[w]){
dfs(isVisited, w);
}
//获取当前结点的下一个结点
w = getNextNeighbour(i, w);
}
}
public void dfs(){
for (int i = 0; i< getNumVertex(); i++){
if (!isVisited[i]) {
dfs(isVisited, i);
}
}
}
//返回边的数目
public int getNumEdge(){
return numEdge;
}
//返回节点的数目
public int getNumVertex(){
return vertexList.size();
}
//返回结点i(下标)对应的数据。‘0’->'A' , '1'->'B'
public String getValueByIndex(int i){
return vertexList.get(i);
}
//返回两个结点之间的权值
public int getWeight(int v1,int v2){
return edges[v1][v2];
}
}
AI 代码解读