有向图的深度优先搜索和广度优先搜索

来源:互联网 发布:java怎么求最小公倍数 编辑:程序博客网 时间:2024/05/16 01:56

上一篇写了有向图的拓扑排序,紧跟着用这个图坐了深度优先和广度优先的搜索,对其中的节点类Vertex做了些许改进,一个是加了访问状态isVisited,还有在Graph类中新加了一个方法用来寻找以节点ver出发的所有节点,和之前寻找所有的相邻节点(包括发出的和指向该节点的)有所不同

代码和结果如下:

广度优先搜索:

import java.util.ArrayList;import java.util.LinkedList;import com.Algorithm.TopSort.Graph;import com.Algorithm.TopSort.Vertex;public class BFStest {Graph g;/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubBFStest bfs = new BFStest();bfs.BFSrecursion(bfs.g);}public BFStest(){g = new Graph();g.buildGraph();}public void BFSrecursion(Graph g){LinkedList<Vertex> queue = new LinkedList<Vertex>();Vertex[] v = g.v; for(int i=0;i<v.length;i++){//先将入度为0的节点放入队中if(g.getEnterEdgeNumber(v[i]) == 0){v[i].setIsVisted(true);queue.add(v[i]);}}System.out.println("广度优先搜索的遍历顺序为:");while(!queue.isEmpty()){Vertex ver = queue.poll();System.out.print(ver.getFrom()+ " ");ArrayList<Vertex> al = g.getDirectedAdjacentVertex(ver);for(Vertex vertex : al){if(!vertex.getIsVisted()){vertex.setIsVisted(true);queue.add(vertex);}}}}}
图Graph类:

package com.Algorithm.TopSort;import java.util.ArrayList;import java.util.Scanner;public class Graph {public Vertex[] v ;public  Edge[] e;public  int edgeNumber;public  int vertexNumber;//根据输入建立一个有向图public void buildGraph(){System.out.print("输入顶点数和边数:");Scanner s = new Scanner(System.in);vertexNumber = s.nextInt();edgeNumber = s.nextInt();System.out.println();//建立顶点数组 v = new Vertex[vertexNumber]; e = new Edge[edgeNumber]; System.out.println("输入顶点名称:"); for(int i = 0;i < vertexNumber ;  i++) { String name = s.next(); v[i] = new Vertex(name); }  for(int i = 0;i< edgeNumber ; i++){System.out.print("输入起点和终点:"); String startVertex = s.next();String endVertex = s.next();//找到起点的vertex索引值int vBeginIndex=findvIndex(startVertex),vEndIndex=findvIndex(endVertex);e[i]= new Edge(endVertex);//由终点建立到该终点的边v[vEndIndex].indegree++;//相应Vertex的入度+1//e[i].eIndex = i;e[i].nextEdge = v[vBeginIndex].first;//将该边的下一条边连接到以startVertex的所有边v[vBeginIndex].first = e[i];//将e作为v[startVertex]的第一条边}}public int getLength(){return v.length;}//返回一个包含相邻节点的ArrayListpublic ArrayList<Vertex> getAdjacentVertex(Vertex ver){int index ;ArrayList al = new ArrayList();//找到指向ver的相邻节点for(int j=0; j < v.length;j++){if(v[j].first != null )for(Edge e = v[j].first;e!=null;e= e.nextEdge)if(e.to.equals(ver.from)){al.add(v[j]);}}index = findvIndex(ver.from);//找到以ver为起点指向的相邻节点for(Edge e = v[index].first;e != null; e = e.nextEdge){al.add( v[findvIndex(e.to)] );}return al;}//返回一个节点的入度(有几个节点直接指向该节点)public int getEnterEdgeNumber(Vertex ver){int counter =0 ;for(int i =0;i<edgeNumber; i++){if(e[i].to.equals(ver.from))counter++;}return counter;}public int findvIndex(String s){int vIndex=-1;for(int j=0;j<v.length;j++){if(v[j].from.equals(s))vIndex = j;}return vIndex;}public ArrayList<Vertex> getDirectedAdjacentVertex(Vertex ver){int index ;ArrayList al = new ArrayList();index = findvIndex(ver.from);//找到以ver为起点指向的相邻节点for(Edge e = v[index].first;e != null; e = e.nextEdge){al.add( v[findvIndex(e.to)] );}return al;}}
边Edge类:
class Edge {String to;//边指向的节点public String getTo() {return to;}public void setTo(String to) {this.to = to;}Edge nextEdge;//具有同一起点的下一条边public Edge(String to) {// TODO Auto-generated constructor stubthis.to = to;this.nextEdge = null;}}
节点Vertex类:

/* * 表示图中的点,其成员有自身关键字和一条以该节点为起点的边 */public class Vertex {String from;//边的起点boolean isVisted = false;public boolean getIsVisted() {return isVisted;}public void setIsVisted(boolean isVisted) {this.isVisted = isVisted;}public String getFrom() {return from;}public void setFrom(String from) {this.from = from;}int indegree;//每个顶点的入度Edge first;//以from为起点的第一条边public Vertex(String from){this.from = from;first = null;this.indegree = 0;}}
运行结果:

输入顶点数和边数:7 6
输入顶点名称:
a b c d e f g 
输入起点和终点:a c 
输入起点和终点:a d
输入起点和终点:b d
输入起点和终点:b e
输入起点和终点:f e
输入起点和终点:f g
广度优先搜索的遍历顺序为:
a b f d c e g


深度优先遍历:

import java.util.ArrayList;import java.util.Stack;import com.Algorithm.TopSort.*;public class DFStest {Graph g;/** * @param args对一个图进行深度优先遍历 */public static void main(String[] args) {// TODO Auto-generated method stubDFStest dfs = new DFStest();dfs.dfsRecursion(dfs.g);}//构造函数public DFStest(){g = new Graph();g.buildGraph();}public void dfsRecursion(Graph g){Stack<Vertex> stack = new Stack<Vertex>();Vertex[] v = g.v;//先把入度为0的节点压入栈,这些是算法开始的起点,若没有,则无法开始算法for(int i =0;i<v.length;i++){if(g.getEnterEdgeNumber(v[i]) == 0){stack.push(v[i]);v[i].setIsVisted(true);}}System.out.println("深度优先搜索的顺序是:");while(!stack.empty()){//把栈顶元素pop并输出Vertex ver = stack.pop();System.out.print(ver.getFrom()+" ");ArrayList<Vertex> al = new ArrayList<Vertex>();al = g.getDirectedAdjacentVertex(ver);for(Vertex vertex : al){//如果没被访问过,则将这些相邻元素进行入栈if( !vertex.getIsVisted() ){vertex.setIsVisted(true);stack.push(vertex);}}}}}

运行结果为:

输入顶点数和边数:7 6
输入顶点名称:
a b c d e f g
输入起点和终点:a c 
输入起点和终点:a d
输入起点和终点:b d
输入起点和终点:b e
输入起点和终点:f e
输入起点和终点:f g
深度优先搜索的顺序是:
f e g b d a c 



0 0