在说图的广度遍历和深度遍历之前,我们可以回想下,树的先序遍历和层次遍历,先序遍历我们是不是从根节点一直递归到叶子节点,然后再慢慢回退,图的深度遍历也是类似的。
图的深度遍历,只需要额外一个数组记录顶点是否有访问过,下面就使用矩阵来实现图,和图的深度遍历。
private boolean[] isVisited = new boolean[n];
private int[][] edges;
public void dfs(int n){
System.out.print(n);
isVisited[n] = true;
int w = getFirstNeigphbor(n);
while(w != -1){
if(!isVisited[w]){
dfs(n);
}
w = getNextNeigphbor(n, w);
}
}
public void getFirstNeigphbor(int n){
int[] edge = edges[n];
for(int i = 1; i < edge.length; i++) {
if(edge[i] == 1){
return i;
}
}
return -1;
}
public void getFirstNeigphbor(int n, int w){
int[] edge = edges[n];
for(int i = w + 1; i < edge.length; i++) {
if(edge[i] == 1){
return i;
}
}
return -1;
}
这里就只给出了深度遍历的必要的几个方法,基本的图数据结构自己可以实现下,如果是不连通图,我们可以再加一个循环,依次遍历每一个顶点,这里就是简单的实现,也没有啥优化,等以后我学了优化再来补吧。
下面就是广度遍历了,先介绍它的基本思想吧,它和树的层次遍历很相似,也是使用队列的特性,把初始节点添加进去,当元素出队列的时候我们就需要把它相邻的节点依次入队,和上面一样我们还需要记录当前节点是否访问过。
public void bfs(int n) {
LinkedList<Integer> queue = new LinkedList();
queue.add(n)
isVisited[n] = true;
while(queue.size() > 0) {
int i = queue.removeFirst();
System.out.print(i);
int w = getFirstNeigphbor(i);
while(w != -1) {
if(!isVisited[w]) {
queue.add(w);
}
w = getNextNeigphbor(i, w);
}
}
}
到此图的深度和广度遍历结束了,后面将会写普利姆算法和克鲁斯卡尔算法。