java实现 图的dfs应用之拓扑排序 以及判断图是否有环

拓扑排序+判断图中是否有环

拓扑排序:从一个顶点开始,进行dfs,直到某一个点再也没有出度,没有出度的点可以认为是最大的点(之一)。
是否有环:为visited数组多添加一个状态:正在被访问状态。如果在一次递归中两次碰到被标记为-1的点,证明成了环

public class Topo {

	//顶点数
	static final int n=4;
	//顶点内容
	static String[] v= {"a","b","c","d"};
	//有向图的邻接矩阵表示法
	static int [][] graph= {
			{0,1,0,0},
			{0,0,0,0},
			{0,1,0,0},
			{0,0,1,0},
	};
	//标记顶点访问状态 1:已经访问过并返回 0:从未访问过 -1:正在递归访问还未退出
	static int [] vis=new int[n];
	//拓扑排序结果
	static int [] topo=new int [n];
	//标记topo数组的哪一位被改写
	static int t=n;
	
	public static void main(String[] args) {
		//对所有顶点进行迭代
		for(int i=0;i<n;i++)
		{
			//如果被访问过,则跳过
			if(vis[i]==1)
				continue;
			//是否有拓扑排序
			boolean bool=dfs(i);
			//如果dfs返回false,证明有环
			if(!bool)
			{
				System.out.println(false);
				return;
			}
		}
		//输出拓扑排序结果
		for(int i=0;i<n;i++)
			System.out.println(v[topo[i]]);
	}

	private static boolean dfs(int i) {
		// 改为正在访问状态
		vis[i]=-1;
		//遍历所有顶点
		for(int j=0;j<n;j++)
		{
			if(graph[i][j]>0)//大于0证明的当前顶点i到顶点j有出度
			{
				//此处,关于顶点j的递归还没有退出,前驱的状态是-1,后继的状态也是-1,说明在此递归的链路上早就路过了j,现在是第二次路过j
				//一次递归,两次经过同一个顶点,只有一种情况,形成了环
				if(vis[j]<0)
					return false;
				//j没被访问过,执行递归
				if(vis[j]==0&&dfs(j)==false)
					return false;//有环
			}
		}
		//for循环走完证明递归走到了末端,该顶点的再无未被访问过的邻居,也就是再无出度
		//此时应该将该点更新到topo数组中
		topo[--t]=i;
		vis[i]=1;
		return true;
	}
	
}

发布了24 篇原创文章 · 获赞 10 · 访问量 1286

猜你喜欢

转载自blog.csdn.net/qq_41625102/article/details/104487400