无向图
用DFS和BFS对无向图进行遍历搜索,所以先实现无向图,这里用队列实现邻接表,代码如下:
public class Undiagraph {
private final int vertexNumber; // 顶点数
private int edgeNuumber; // 边数
static Queue<Integer>[] adj; // 邻接表,用队列实现(二维)
// 无向图构造器
@SuppressWarnings("unchecked")
public Undiagraph(int vertexNumber) {
this.vertexNumber = vertexNumber;
this.edgeNuumber = 0;
//初始化邻接表adj
adj = new Queue[vertexNumber];
for (int i = 0; i < vertexNumber; i++)
adj[i] = new LinkedList<Integer>(); // 因为Queue是接口,所以用链表进行初始化
}
public int getVertexNumber() {
return vertexNumber;
}
public int getEdgeNumber() {
return edgeNuumber;
}
// 向邻接表中添加边
public void addEdge(int oldNode, int newNode) {
// 这里和有向图的添加边的方法有区别
adj[oldNode].add(newNode); // 将newNode添加到oldNode的链表中
adj[newNode].add(oldNode); // 将oldNode添加到newNode的链表中
edgeNuumber++;
}
// 由node指出的边所连接的所有顶点
public Iterable<Integer> adj(int node) {
return adj[node];
}
}
1、深度优先搜索(DFS)
/**
* 1、深度优先搜索:类似于树的先序遍历
* @param graph 图
* @param startNode 开始顶点
*
* 重要变量:
* adj
* startNode
* visited 全局变量
*/
public static void DepthFirstSearch(Undiagraph graph, int startNode) {
visited = new boolean[graph.getVertexNumber()]; // 初始化标记数组
dfs(graph, startNode); // 调用递归方法
}
/**
* 递归方法
* @param graph 图
* @param startNode 开始结点,会随着递归的进行变化
*
* 重要变量:
* adj
* startNode
* visited 全局变量
*/
public static void dfs(Undiagraph graph, int startNode) {
visited[startNode] = true;
System.out.print(startNode + " ");
for (int i : graph.adj(startNode)) { // 递归的第一个限制条件
if (!visited[i]) dfs(graph, i); // 递归的第二个限制条件
}
}
输入以下图进行深度优先搜索:
执行深度优先搜索的递归过程如下图:
代码执行结果如下:
输入上述无向图
输出:
0 1 2 3 4 5
2、广度优先搜索(BFS)
/**
* 2、广度优先搜索
* @param graph 图
* @param startNode 开始顶点
*
* 重要变量:
* adj
* startNode
* visited 全局变量
* queue 该队列保存所有已经被标记过但其邻接表还未被检查过的顶点
*/
public static void BreadthFirstSearch(Undiagraph graph, int startNode) {
visited = new boolean[graph.getVertexNumber()]; // 初始化标记数组
Queue<Integer> queue = new LinkedList<>(); // 初始化队列
queue.add(startNode); // 将开始结点加入队列
visited[startNode] = true;
/* 1、取队列中的下一个顶点node并标记它
* 2、检查node对应的邻接表,将与node相邻且未被标记的点入队
* 3、循环上述1、2步骤直到队列为空
*/
while (!queue.isEmpty()) {
int node = queue.poll();
System.out.print(node + " ");
for (int j : graph.adj(node)) {
if (!visited[j]) {
queue.add(j);
visited[j] = true; // 将顶点入队,该顶点已经被标记但其邻接表还未被检查
}
}
}
}
代码执行结果如下:
输入上述无向图
输出:
0 1 3 2 4 5
main函数:
public static void main(String[] args) {
Undiagraph graph = new Undiagraph(6);
// 将边添加到邻接表中
graph.addEdge(0, 1);
graph.addEdge(0, 3);
graph.addEdge(1, 0);
graph.addEdge(1, 2);
graph.addEdge(1, 3);
graph.addEdge(1, 4);
graph.addEdge(2, 1);
graph.addEdge(2, 3);
graph.addEdge(2, 4);
graph.addEdge(2, 5);
graph.addEdge(3, 0);
graph.addEdge(3, 1);
graph.addEdge(3, 2);
graph.addEdge(3, 4);
graph.addEdge(4, 1);
graph.addEdge(4, 2);
graph.addEdge(4, 3);
graph.addEdge(4, 5);
graph.addEdge(5, 2);
graph.addEdge(5, 4);
DepthFirstSearch(graph, 0);
System.out.println();
BreadthFirstSearch(graph, 0);
}