一、深度优先搜索(DFS)
每次都在访问完当前节点后首先访问当前节点的第一个邻接节点,可以看出这是一个递归的过程。
深度优先遍历算法步骤:
1、访问初始尾结点v,并标记结点v已经访问
2、查找结点v的第一个领接结点
3、若w存在,则继续执行4,若w不存在,则回到第一步,将从v的下一个结点继续
4、若w未被访问,对w进行深度优先遍历递归(即把w当做另一个v,然后进行步骤123)
5、查找结点v的w邻接结点的写一个邻接结点,转到步骤3
具体问题分析:
A | B | C | D | E | |
A | 0 | 1 | 1 | 0 | 0 |
B | 1 | 0 | 1 | 1 | 1 |
C | 1 | 1 | 0 | 0 | 0 |
D | 0 | 1 | 0 | 0 | 0 |
E | 0 | 1 | 0 | 0 | 0 |
// 说明
// 1表示能够直连,0表示不能直接连接
深度优先搜索过程:
A-B-C-D-E,A和B和C能够联通,联通为“1”;B和A、C、D、E联通;C和A、B联通;D和B联通,E和B联通。
A连接B,找到B后,B连接C,C联通不了别的节点,就再回到B,B联通D,B联通E。(找到哪个点就不变了,一条道走到黑)。
代码:
/得到第一个结点的下标
public int getfirstNeighbor(int index){
for(int j=0;j<vertexList.size();j++){
if(edges[index][j]>0){
return j;
}
}
return -1;
}
//根据前一个邻接结点的下标来获取下一个邻接节点
public int getNextNeighbor(int v1,int v2){
for(int j=v2+1;j<vertexList.size();j++){
if(edges[v1][j]>0){
return j;
}
}
return -1;
}
//深度优先遍历
/* isVisited[] 记录结点是否访问的数组
* i 第一次是0
*/
public void dfs(boolean[] isVisited,int i){
//首先访问该节点,输出
System.out.print(getValueByIndex(i)+"->");
isVisited[i]=true;
int w=getfirstNeighbor(i);
while(w!=-1){
//说明有邻接结点
if(!isVisited[w]){
dfs(isVisited,w);
}
//如果该结点被访问
w=getNextNeighbor(i,w);
}
}
//重载dfs方法
public void dfs(){
isVisited=new boolean[vertexList.size()];
//遍历所有的结点进行dfs回溯
for(int i=0;i<vertexList.size();i++){
if(!isVisited[i]){
dfs(isVisited,i);
}
}
}
二、图的广度优先遍历(BFS)
广度优先遍历基本思想类似于一个分层搜索的过程,需要使用一个队列以保持访问过的结点的顺序,方便按照这个顺序来访问这些结点的领接结点。
算法步骤:
1访问初始结点v并标记结点v已经访问
2结点v入队列
3当队列非空时,继续执行,否则算法就结束
4出队列,取得队头节点u
5查找节点u的第一个领接结点v
6若结点u的领接结点w不存在,则转移到步骤3,否则循环执行以下三个步骤
6.1若结点w尚未被访问,则访问结点w并标记已经访问
6.2结点w入队列
6.3查找结点u的继w领接结点后的下一个领接结点,转移到步骤6.
查找过程如下:
A找到B,再找B的后继结点C,A可以找到C,此时B在队列中,将B弹出,从B结点找,此时A结点已经被访问过,C也被访问过,此时D被访问到了,E也可以访问到.
也就是,B和C由A访问到,D和E由A结点访问到。
//广度优先遍历
public void bfs(boolean isVisited[],int i){
int u; //表示队列的头结点对应下标
int w; //邻接结点
//队列,记录访问结点的顺序
LinkedList queue=new LinkedList();
//输出访问结点信息
System.out.println(getValueByIndex(i)+"->");
//标记为已访问
isVisited[i]=true;
//将一访问的结点加入队列
queue.addLast(i);
while(!queue.isEmpty()){
//取出队列的头结点下标
u=(Integer)queue.removeFirst();
//得到第一个邻接结点的下标
w=getfirstNeighbor(u);
while(w!=-1){
//是否访问过
if(!isVisited[w]){
System.out.println(getValueByIndex(w)+"->");
//标记为已访问
isVisited[w]=true;
//入队
queue.addLast(w);
}
//以u为前驱点,找w后面的下一个结点
w=getNextNeighbor(u,w);
}
}
}
//遍历所有的结点,都进行广度优先搜索
public void bfs(){
isVisited=new boolean[vertexList.size()];
for(int i=0;i<vertexList.size();i++){
if(!isVisited[i]){
bfs(isVisited,i);
}
}
}
get!