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

上一篇写了有向图的拓扑排序,紧跟着用这个图坐了深度优先和广度优先的搜索,对其中的节点类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 stub
		BFStest 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;
	}
	
	//返回一个包含相邻节点的ArrayList
	public 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 stub
		this.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 stub

		DFStest 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
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值