代码示例
import java.util.*;
public class Main {
public static void main(String[] args) {
Graph gra = new Graph(10);
gra.addEdge(0,2);
gra.addEdge(2,3);
gra.addEdge(3,6);
gra.addEdge(0,3);
gra.addEdge(0,9);
gra.addEdge(2,9);
System.out.println("深度优先遍历");
gra.DFS(0);
Graph gra2 = new Graph(10);
gra2.addEdge(0,2);
gra2.addEdge(2,3);
gra2.addEdge(3,6);
gra2.addEdge(0,3);
gra2.addEdge(0,9);
gra2.addEdge(2,9);
System.out.println("广度优先遍历");
gra2.BFS(0);
}
}
class Graph{
private int V;
private Node adj[];
public Graph(int v){
V = v;
adj = new Node[v];
for(int i=0; i < v; i++){
Node node = new Node(i);
adj[i] = node;
}
root = adj[0];
}
public void addEdge(int v, int w){
if(v<=V && w <= V){
adj[v].addEdge(w);
} else {
System.out.println("异常数据");
}
}
// 深度优先遍历
public void DFS(int v) {
// 将当前顶点设置为已遍历
adj[v].visited = true;
Iterator<Integer> i = adj[v].getAdj().listIterator();
while(i.hasNext()){
int n = i.next();
if(!adj[n].visited){
System.out.println(v + "->" + n);
DFS(n);
}
}
}
// 广度优先遍历,在遍历当前节点的下一级节点前,先遍历当前节点的相邻节点
public void BFS(int v){
Queue<Integer> queue = new LinkedList<Integer>();
adj[v].visited = true;
// 添加到队列尾部
queue.add(v);
while(!queue.isEmpty()){
// 出列
int i = queue.poll();
Iterator<Integer> iter = adj[i].getAdj().listIterator();
while(iter.hasNext()){
int n = iter.next();
if(!adj[n].visited){
adj[n].visited = true;
// 暂时不遍历其下级节点,先遍历相邻节点
queue.add(n);
System.out.println(i + "->" + n);
}
}
}
}
}
class Node{
public boolean visited = false;
private int c;
private LinkedList<Integer> adj;
public Node(){
}
public Node(int v){
this.c = v;
this.adj = new LinkedList();
}
public LinkedList<Integer> getAdj(){
return adj;
}
public void addEdge(int n){
this.adj.add(n);
}
}
运行结果:
深度优先遍历(DFS)
优先遍历节点的子节点,再遍历节点的相邻节点。
A -- B -- C
| |
D -- E -- F
这是一个简单的无向图,其中 A、B、C、D、E 和 F 是图中的顶点,-- 表示顶点之间的边。
现在,我们以 A 为起点,来演示如何进行图的深度优先遍历。
深度优先遍历的基本思路是:
从起点开始,访问与之相邻的顶点,并递归地访问与这些相邻顶点相邻的未访问过的顶点,直到所有可达的顶点都被访问过为止。
具体地,以 A 为起点,深度优先遍历的访问顺序如下:
- 访问顶点
A,将其标记为已访问。 - 访问
A的相邻顶点B,将其标记为已访问。 - 访问
B的相邻顶点C,将其标记为已访问。 C没有未访问过的相邻顶点,回溯到B。- 访问
B的相邻顶点D,将其标记为已访问。 - 访问
D的相邻顶点E,将其标记为已访问。 - 访问
E的相邻顶点F,将其标记为已访问。 F没有未访问过的相邻顶点,回溯到E。E没有未访问过的相邻顶点,回溯到D。D没有未访问过的相邻顶点,回溯到B。B的所有相邻顶点都已被访问,回溯到A。A的相邻顶点D已经访问过,回溯到结束。
因此,深度优先遍历的访问顺序是 A、B、C、D、E 和 F。
注意,深度优先遍历使用的是递归方式,因此需要使用栈来记录访问的顶点。
在实际的实现中,也可以使用递归调用来代替显示的栈。
广度优先遍历(BFS)
优先遍历节点的相邻节点,再遍历节点的子节点。
A -- B -- C
| |
D -- E -- F
继续以上图来演示
现在,我们以 A 为起点,来演示如何进行图的广度优先遍历。
广度优先遍历的基本思路是:
从起点开始,访问与之距离为 1 的顶点,并将这些顶点标记为已访问, 然后访问与这些顶点距离为 2 的顶点,将它们标记为已访问,依次类推,直到所有可达的顶点都被访问过止。
具体地,以 A 为起点,广度优先遍历的访问顺序如下:
- 访问顶点
A,将其标记为已访问。 - 访问
A的相邻顶点B,将其标记为已访问,并将其加入队列。 - 访问
A的相邻顶点D,将其标记为已访问,并将其加入队列。 - 从队列中取出下一个顶点
B,访问B的相邻顶点C,将其标记为已访问,并将其加入队列。 - 从队列中取出下一个顶点
D,访问D的相邻顶点E,将其标记为已访问,并将其加入队列。 - 从队列中取出下一个顶点
C,C没有未访问过的相邻顶点。 - 从队列中取出下一个顶点
E,访问E的相邻顶点F,将其标记为已访问,并将其加入队列。 F没有未访问过的相邻顶点。- 队列为空,结束遍历。
因此,广度优先遍历的访问顺序是 A、B、D、C、E 和 F。
注意,广度优先遍历使用的是队列,因此需要将已访问过但未访问过相邻顶点的顶点加入队列。
在实际的实现中,也可以使用递归调用来代替队列。