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

xiaoxiao2021-02-28  102

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[n][n]; 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); } }

转载请注明原文地址: https://www.6miu.com/read-71827.html

最新回复(0)