上篇博文介绍了采用先深后广的方式遍历图形,本文介绍采用先广后深的方式来遍历图形。所谓先广后深法,就是优先遍历列表中当前访问链接的所有节点,再访问其他链接的节点。与先深后广法访问的顺序采用了堆栈结构不同,先广后深法采用的是队列的结构。也即,将当前访问节点相连的所有节点放入队列,访问队列头,再将与当前访问的节点相连且未被访问过的节点放入队列,循环执行此步骤,直至队列为空。依然以以下两个图形为例:
对于左图,若以A为起点,则有:
step 1:选取A,将未被访问的相邻节点B,D,E送入队列,同时标记B,D,E为已被访问
B | D | E |
step 2:选取B,将未被访问的相邻节点C送入队列,同时标记C为已被访问
D | E | C |
E | C |
C |
具体实现代码如下:
package javaTest;
import java.util.Arrays;
public class BFS {
static int queueSize = 10;
static int[] queue = new int[queueSize];//定义队列
static int queueHead = -1;//队列头指针
static int queueTail = -1;//队列尾指针
public static void queueReset(){//重置队列
Arrays.fill(queue, 0);
queueHead = -1;
queueTail = -1;
}
public static void queueAdd(int value){//往队列添加数据
queueTail++;
queue[queueTail] = value;
}
public static int queueGet(){//从队列中取数据
if(queueHead==queueTail){
System.out.println("The queue is empty");
return -1;
}
queueHead++;
return(queue[queueHead]);
}
public static void bfs(int x, GraphList list){
System.out.print("["+x+"] ");
list.state[x] = 1;
Node tempNode = list.links[x].head;
while(tempNode!=null){//将与当前访问节点相连的节点依次放入队列
if(list.state[tempNode.value]==0){
queueAdd(tempNode.value);
list.state[tempNode.value] = 1;
}
tempNode = tempNode.nextNode;
}
if(queueHead!=queueTail){//如果队列不为空,则继续从队列取数据和放入数据的操作
bfs(queueGet(), list);
}
}
public static void main(String[] args){
int[][] data1 = {
{1,2},{2,1},{1,4},{4,1},
{1,5},{5,1},{2,3},{3,2},
{2,4},{4,2},{3,4},{4,3},
{3,5},{5,3}
};
int[][] data2 = {
{1,2},{1,5},{2,4},{3,2},
{3,4},{4,1},{5,3}
};
System.out.println("Breadth-first search of the undirected graph:");
GraphList list1 = new GraphList(data1);
bfs(1,list1);
System.out.println();
queueReset();
System.out.println("Breadth-first search of the directed graph:");
GraphList list2 = new GraphList(data2);
bfs(1,list2);
}
}
class GraphList {//列表类,每一个列表有n个链接类构成,n为节点的个数
int nodeNumber;
int[] state;
GraphLink[] links;
public GraphList(int[][] data){
nodeNumber = 0;
for(int i=0; i<data.length; i++){//判断初始数据中提供的节点的个数
for(int j=0; j<data[i].length; j++){
if(nodeNumber<data[i][j]){
nodeNumber = data[i][j];
}
}
}
state = new int[nodeNumber+1];
links = new GraphLink[nodeNumber+1];
for(int i=1; i<links.length; i++){
state[i] = 0;
links[i] = new GraphLink();
for(int j=0; j<data.length; j++){
if(data[j][0]==i){
links[i].insert(data[j][1]);
}
}
}
}
}
class Node{//节点类
int value;
Node nextNode;
public Node(int value){
this.value = value;
nextNode = null;
}
}
class GraphLink{//链接类
Node head;
Node tail;
public boolean isEmpty(){
return head==null;
}
public void print(){//打印链接
Node tempNode = head;
while(tempNode != null){
System.out.print("["+tempNode.value+"] ");
tempNode = tempNode.nextNode;
}
}
public void insert(int value){//往链接中插入节点
Node tempNode = new Node(value);
if(this.isEmpty()){
head = tempNode;
tail = tempNode;
}
else{
tail.nextNode = tempNode;
tail = tempNode;
}
}
}
程序输出:
Breadth-first search of the undirected graph:
[1] [2] [4] [5] [3]
Breadth-first search of the directed graph:
[1] [2] [5] [4] [3]