第四周作业——有向无环图的判断

作业要求:按照教材中对有向无环图(DAG)的定义与判断方式,对图(tinyDG.txt),编程实现并判断该G是否有环,进一步找出环的路径(如:v1-v5-v6-v1)。类名:GraphDAG



用java实现无向图的DFS算法,代码如下:

/**
 * 有向无环图的判断
 */
public class GraphDAG {
	
	//vertex,顶点数目
	private int v;
	//edge,边数目
	private int e;
	//邻接矩阵
	private int [][] matrix ;
	
	/**
	 * 初始化
	 * @param v 顶点数目
	 * @param e 边数目
	 */
	public GraphDAG(int vertex, int edge){
		if(edge<0) throw new RuntimeException("Number of edges must be nonnegative");
		if (edge > vertex*vertex) throw new RuntimeException("Too many edges");
		
		this.v = vertex;
		this.e = edge;
		this.matrix = new int[v][v];
	}	
	
	//两个顶点间存在边,设置矩阵值
	public void addEdge(int v1, int v2){
		matrix[v1][v2] = 1;
	}
	
	//获取邻接矩阵
	public int[][] getAdjacencyMatrix(){ return matrix; }
	
	/**
	 * 获取环路路径
	 * @param cc 强连通分量集合
	 * @return 各个强连通分量的环路路径
	 */
	public List<String> getCyclePath(List<GraphNode[]> cc){
		List<String> list = new ArrayList<String>();
		int count = cc.size();			
		
		//遍历每个强连通分量,在其内部寻找环路
		for(int i=0; i<count; i++){
			GraphNode[] c = cc.get(i);
			int len = c.length;
			
			//取出强连通分量集合的所有顶点名-->数组,方便查找
			int [] sortSequence = new int[len];
			int num = 0 ;		
			//
			//sortSequence:
			//name :0	1	5	4	2	3
			//index:0	1	2	3	4	5
			//
			for(GraphNode node : c){
				sortSequence[num++] = node.getName();
			}
			
			for(int j=0; j<len; j++){				
				//取出边(u,v)的u顶点
				int vertex1 = sortSequence[j];
				for(int k=0; k<len; k++){					
					//取出边(u,v)的v顶点
					int vertex2 = sortSequence[k];
					
					//关键!!! 在有向无环图中,每条边都指向一个post值更小的顶点( post(u)>post(v) )
					//即对于回边有: post(u)<post(v)~~~
					if(matrix[vertex1][vertex2] == 1 && c[j].getPost()<c[k].getPost()){
						
						StringBuffer sb = new StringBuffer();
						for(int n=k; n<j; n++){
							//注意!!! 环的路径中,每条边都指向一个post值更小的顶点
							if(c[n].getPost()>c[n+1].getPost()){
								sb.append(sortSequence[n]+"-");
							}
						}
						sb.append(vertex1 + "-" + vertex2);		
						list.add(sb.toString());
					}
				}
			}
			
		}
		
		return list;
	}
}
	

GraphNode请见: 第四周作业——无向图的DFS算法

测试代码:

	public static void main(String[] args){
		
		try(Scanner scanner = new Scanner
			(GraphDAG.class.getClassLoader().getResourceAsStream("tinyDG.txt"));
			PrintWriter out = new PrintWriter(new File("tinyG_matrix.txt"));){
			
			//第一行的数字是顶点的数目
			int v = scanner.nextInt();
			//第二行的数字是边的数目
			int e = scanner.nextInt();
			GraphDAG graph = new GraphDAG(v, e);
			
			//读取每条边对应的两个顶点,设置邻接矩阵的值
			for (int i = 0; i < e; i++) {				
				int v1 = scanner.nextInt();
				int v2 = scanner.nextInt();
				graph.addEdge(v1, v2);
			}
			
			//根据graph的邻接矩阵,对其进行深度优先搜索
			int matrix[][] = graph.getAdjacencyMatrix();
			GraphDFS graphDFS = new GraphDFS(matrix);
			
			//使用无向图的深度优先搜索,对该有向图进行(参照"第四周作业——无向图的DFS算法")
			graphDFS.dfs();		
			
			//强连通分量集合
			List<GraphNode[]> cc = graphDFS.getCC();
			List<String> pathList =  graph.getCyclePath(cc);		
			
			if(pathList.size()>0){
				System.err.println("存在环路,环路路径如下:\n");
				
				int num = 1;
				for(String path : pathList){
					System.err.println("第" + (num++) + "个环路,路径为: " + path);
				}
			}else{
				System.err.println("该图不存在存在环路!");				
			}
					
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		}	
		
	}

测试结果(有bug,待修正...):



本算法的关键:

在有向无环图中,每条边都指向一个post值更小的顶点;

判断有向图是否有环路,只需判断是否有回边即可,再对这些回边的起始顶点进行DFS,找到起始顶点到终端顶点的路径即为环路的路径. 

对于起始顶点进行DFS还未实现,故当一条回边被多个环路共同拥有时出错,方法正在寻找中...

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值