您的位置:首页 > 其它

图的深度优先搜索(DFS)和广度优先搜索(BFS)

2017-07-11 16:56 417 查看
1.遍历

图的遍历,所谓遍历,就是对结点的访问,一个图有那么多的结点,如何遍历这些结点,需要特定的策略,一般有两种访问策略:

深度优先搜索和广度优先搜索

2.深度优先搜索DFS


深度优先搜索,从图的任一顶点V1开始,输出顶点V1,将V1作为当前顶点,寻找当前顶点的邻接点V2,并进行如下判断:如果目前尚未输出顶点V2,则输出V2,V2成为新的当前顶点,继续这个过程;如果V2已经输出,则检查V1的另一个邻接点;如果V1的所有邻接点均已输出,则退回到V1之前的顶点深度优先搜索过程是一个递归过程,程序实现时使用栈记录遍历路径,当遍历一个顶点时,顶点入栈;当某个顶点的所有邻接点均已访问过,则退栈,栈顶顶点又作为当前顶点,继续遍历过程。当栈空时,检查是否已遍历图中所有顶点,若是,说明图为连通图,否则,图是不连通的

具体算法表述如下:

访问初始结点v,并标记结点v为已访问。

查找结点v的第一个邻接结点w。

若w存在,则继续执行4,否则算法结束。

若w未被访问,对w进行深度优先遍历递归(即把w当做另一个v,然后进行步骤123)。

查找结点v的w邻接结点的下一个邻接结点,转到步骤3。

例如下图,其深度优先遍历顺序为 
1->2->4->8->5->3->6->7




3.广度优先搜索BFS


广度优先搜索是一个迭代的过程,类似于二叉树层序遍历过程,从图中的任一顶点V1开始,将顶点V1入队列,当队列不空时,循环执行:出队列,并输出该顶点,标记该顶点为已输出,将该顶点所有尚未输出的邻接点入队列

具体算法表述如下:

访问初始结点v并标记结点v为已访问。

结点v入队列

当队列非空时,继续执行,否则算法结束。

出队列,取得队头结点u。

查找结点u的第一个邻接结点w。

若结点u的邻接结点w不存在,则转到步骤3;否则循环执行以下三个步骤:
1). 若结点w尚未被访问,则访问结点w并标记为已访问。
2). 结点w入队列
3). 查找结点u的继w邻接结点后的下一个邻接结点w,转到步骤6。


如上图,其广度优先算法的遍历顺序为:1->2->3->4->5->6->7->8
4.程序
package graph;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class Graph {
private ArrayList vertexList; //存储点的链表
private int[][] edges; //邻接矩阵,用来存储边
private Stack<Integer> stack;
private Queue<Integer> queue;

public Graph(int n){
this.vertexList=new ArrayList(n);
this.edges=new int

;
this.stack=new Stack<Integer>();
this.queue=new LinkedList<Integer>();
}

//插入结点
public void insertVertex(Object vertex){
vertexList.add(vertexList.size(), vertex);
}

//插入边
public void insertEdge(int v1,int v2,int weight){
edges[v1][v2]=weight;
}

//深度优先搜索
public void DFS(boolean[] isVisited){
int i=this.stack.peek();
boolean mark=false;
for(int j=0;j<vertexList.size();j++){
if(edges[i][j]>0&&!isVisited[j]){
System.out.print(vertexList.get(j)+"-");
isVisited[j]=true;
this.stack.push(j);
mark=true;
DFS(isVisited);
}
}
if(!mark)
this.stack.pop();
if(this.stack.isEmpty())
return;
}

public void initDFS(boolean[] isVisited){
System.out.print(vertexList.get(0)+"-");
isVisited[0]=true;
this.stack.push(0);
DFS(isVisited);
}

//广度优先搜索
public void BFS(boolean[] isVisited){
if(this.queue.isEmpty())
return;
int i=this.queue.poll();
System.out.print(vertexList.get(i)+"-");
for(int j=0;j<this.vertexList.size();j++){
if(this.edges[i][j]>0&&!isVisited[j]){
isVisited[j]=true;
this.queue.add(j);
}
}
BFS(isVisited);
}

public void initBFS(boolean[] isVisited){
this.queue.add(0);
isVisited[0]=true;
}

public static void main(String[] args){
int n=8;
String labels[]={"1A","2B","3C","4D","5E","6F","7G","8H"};
Graph graph=new Graph(n);
for(String label:labels)
graph.insertVertex(label);
//插入九条边
graph.insertEdge(0, 1, 1);
graph.insertEdge(0, 2, 1);
graph.insertEdge(1, 3, 1);
graph.insertEdge(1, 4, 1);
graph.insertEdge(3, 7, 1);
graph.insertEdge(4, 7, 1);
graph.insertEdge(2, 5, 1);
graph.insertEdge(2, 6, 1);
graph.insertEdge(5, 6, 1);
graph.insertEdge(1, 0, 1);
graph.insertEdge(2, 0, 1);
graph.insertEdge(3, 1, 1);
graph.insertEdge(4, 1, 1);
graph.insertEdge(7, 3, 1);
graph.insertEdge(7, 4, 1);
graph.insertEdge(6, 2, 1);
graph.insertEdge(5, 2, 1);
graph.insertEdge(6, 5, 1);

System.out.println("深度优先搜索序列为:");
boolean[] isVisited=new boolean[8];
graph.initDFS(isVisited);
graph.DFS(isVisited);
System.out.println();
System.out.println("广度优先搜索序列为:");
isVisited=new boolean[8];
graph.initBFS(isVisited);
graph.BFS(isVisited);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: