`
128kj
  • 浏览: 604129 次
  • 来自: ...
社区版块
存档分类
最新评论

深度优先搜索与有向无环图的拓扑排序(java实现)

    博客分类:
阅读更多
   当每个任务有前后置关系时,需要找到一种满足前后置关系的路线,将任务完成。

如果将每个任务看成一个节点,任务之间的前后置关系表示为有向图时,这种路线顺序叫做为图进行拓扑排序。也叫关键路径分析。

比如有很多任务T1,T2,....
    这些任务又是相互关联的,比如Tj完成前必须要求Ti已完成,这样T1,T2....序列关于这样的先决条件构成一个图,其中如果Ti必须要先于Tj完成,那么<Ti,Tj>就是该图中的一条路径,路径长度为1的就是一条边。拓扑排序就是把这些任务按照完成的先后顺序排列出来。显然,这样的顺序可能不是唯一的,比如Tk,Tl如果没有在一条路径上,那么他们之间的顺序是任意的。


    当从某顶点v出发的DFS搜索完成时,v的所有后继必定均已被访问过(想像它们均已被删除),此时的v相当于是无后继的顶点,因此在DFS算法返回之前输出顶点v即可得到 DAG的逆拓扑序列。
其中第一个输出的顶点必是无后继(出度为0)的顶点,它应是拓扑序列的最后一个顶点。若希望得到的不是逆拓扑序列,同样可增加T来保存输出的顶点。假设T是栈。
利用DFS求拓扑序列的抽象算法可描述为:
void DFSTopSort(G,i,T){//i是搜索的出发点,T是栈
  int j;
  visited[i]=TRUE; //访问i
  for(所有i的邻接点j)//即<i,j>∈E(G)
  if(!visited[j])
    DFSTopSort(G,j,T);
   Push(&T,i); //从i出发的搜索已完成,输出i
}

看看下图的一个拓扑序列:

[c1, c4, c0, c2, c3, c5, c6, c7, c8]




public enum VertexState {
	UNVISITED,VISITED,PASSED;//未访问,已访问,已经过
}

import java.util.Set;
import java.util.List;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.Collections;

//顶点类
class Vertex
   {
    private String label;        
    private VertexState state;//顶点状态

   public Vertex(String lab)   
      {
      label = lab;
      state = VertexState.UNVISITED;
      }
 

   public VertexState getState(){
         return state;
   }

   public void setState(VertexState state){
         this.state=state;
   }

   public String toString(){
       return label;
   }

   

   } 

//有向图的邻接矩阵实现
class Graph
   {
   private final int MAX_VERTS = 30;
   private Vertex vertexList[]; // 存放顶点的数组
   private int adjMat[][];      // 邻接矩阵
   private int nVerts;          // 当前的顶点数
 

   public Graph()             
      {
      vertexList = new Vertex[MAX_VERTS];
                                         
      adjMat = new int[MAX_VERTS][MAX_VERTS];
      nVerts = 0;
      for(int y=0; y<MAX_VERTS; y++)      
         for(int x=0; x<MAX_VERTS; x++)   
            adjMat[x][y] = 0;
      
      }  

    public  void addVertex(Vertex v)//在图中添加一个顶点
      {
      vertexList[nVerts++] = v;
      }

  //在图中增加一条边,从start到end
   public void addEdge(int start, int end)
      {
      adjMat[start][end] = 1;
   
      }


       /**
	 * 返回v顶点所关联的邻结点
	 * @param v
	 * @return
	 */
   private Set<Vertex> getNeighbors(Vertex v){
               Set<Vertex> vSet = new HashSet<Vertex>();
	       int index=getIndex(v);
               if(index==-1) return null;
               for(int i=0;i<nVerts;i++)
                  if(adjMat[index][i]==1)
                      vSet.add(vertexList[i]);
            
		return vSet;
	}
       
       //返回顶点在vertexList数组中的索引
     private int getIndex(Vertex v){
          for(int i=0;i<nVerts;i++)
            if(vertexList[i]==v)
                return i;
           return -1;
        }

      /**
	 * 全部节点设为未访问
	 */
    private void allUnVisted(){
	Vertex v=null;
	int len = nVerts;
     for(int i = 0; i < len ; i++){
	v = vertexList[i];
	if(v.getState() != VertexState.UNVISITED){
		v.setState(VertexState.UNVISITED);
	}
      }
    }

    private boolean containsVertex(Vertex v){
         int index=getIndex(v);
         if(index!=-1) return true;
         else return false;
               
		
	}

    private VertexState getState(Vertex v){
		
		return v.getState();
	}

    private VertexState setState(Vertex v, VertexState state) {
		
		VertexState preState = v.getState();
		v.setState(state);
		return preState;
	}

   /**
	 * 深度优先遍历一个顶点
	 * @param 
	 * @param graph
	 * @param v
	 * @param checkCycle
	 * @return
	 */
    public List<Vertex> dfs(Vertex v,boolean checkCycle){
		allUnVisted();
		List<Vertex> vList = new ArrayList<Vertex>();
		dfsHandler(v,checkCycle,vList);
		return vList;
	}

  

      private void dfsHandler(Vertex v,boolean checkCycle,List<Vertex> vList){
          	Set<Vertex> neighbors = null;
		if(!containsVertex(v)){
		 throw new IllegalStateException("不存在该顶点");
		}
		setState(v, VertexState.PASSED);
		
		neighbors = getNeighbors(v);
		VertexState state = null;
		for(Vertex neighbor : neighbors){
		   state = getState(neighbor);
		    if(state == VertexState.UNVISITED){//未遍历,
                             //  System.out.println(neighbor+",");
		       dfsHandler(neighbor, checkCycle, vList);
	}else if(state == VertexState.PASSED && checkCycle){//
                             
		throw new IllegalStateException("存在一个环");
			}
		}
		setState(v, VertexState.VISITED);//访问结束设为已访问
		vList.add(v);
               // System.out.println("++"+v);
               
	}


         /**
	 * 图的拓扑排序
	 */
	public List<Vertex> topo(){
	  List<Vertex> vList = new ArrayList<Vertex>();
	  allUnVisted();
	  for(int i=0;i<nVerts;i++){
	    if(getState(vertexList[i]) == VertexState.UNVISITED){
		try{
		  dfsHandler(vertexList[i], true, vList);
		}catch (IllegalStateException e) {
		  throw new IllegalStateException("图有一个环");
		}
	     }
	  }
	Collections.reverse(vList);
	return vList;
    }

}

public class DFSApp
   {
   public static void main(String[] args)
      {
      Graph theGraph = new Graph();
      Vertex v1=new Vertex("c0");
      Vertex v2=new Vertex("c1");
      Vertex v3=new Vertex("c2");
      Vertex v4=new Vertex("c3");
      Vertex v5=new Vertex("c4");
      Vertex v6=new Vertex("c5");
      Vertex v7=new Vertex("c6");
      Vertex v8=new Vertex("c7");
      Vertex v9=new Vertex("c8");
  
   
      theGraph.addVertex(v1);    // 0  
      theGraph.addVertex(v2);    // 1
      theGraph.addVertex(v3);    // 2
      theGraph.addVertex(v4);    // 3
      theGraph.addVertex(v5);    // 4
      theGraph.addVertex(v6);    // 5  
      theGraph.addVertex(v7);    // 6
      theGraph.addVertex(v8);    // 7
      theGraph.addVertex(v9);    // 8

      theGraph.addEdge(0, 6);     // c0->c6
      theGraph.addEdge(0, 2);     // c0->c2
      theGraph.addEdge(3, 5);     // c3->c5
      theGraph.addEdge(3, 8);     // c3->c8
      theGraph.addEdge(1, 2);     // c1->c2
      theGraph.addEdge(1, 4);     // c1->c4
      theGraph.addEdge(2, 3);     // c2->c3
      theGraph.addEdge(6, 7);     // c6->c7
      theGraph.addEdge(7, 8);     // c7->c8
      theGraph.addEdge(4, 3);     // c4->c3
      theGraph.addEdge(4, 5);     // c4->c5
      //theGraph.addEdge(3, 1);     // c3->c1


      System.out.print("Visits: ");
      List<Vertex> vl=theGraph.topo();    
       // List<Vertex> vl=theGraph.dfs(v1,false);            
      System.out.println(vl);
      }  
   }


下载源文件:
  • 大小: 3.9 KB
分享到:
评论

相关推荐

    深度优先搜索输出有向图中的所有环(JAVA)

    深度优先搜索(DFS, Depth-First Search)是一种用于遍历或搜索树或图的算法,尤其在处理有向图中的环问题时表现出色。在这个场景下,我们的目标是找到有向图中的所有环。Java是实现这个算法的一种常用编程语言。下面...

    图的几种常用算法(广度/深度优先搜索,最小生成树,弗洛伊德,拓扑排序....)java实现,简单易懂。

    本资源包含了一些图算法的Java实现,包括但不限于广度优先搜索(BFS)、深度优先搜索(DFS)、最小生成树(Minimum Spanning Tree, MST)、弗洛伊德算法(Floyd-Warshall)以及拓扑排序。下面将详细介绍这些算法及其...

    本周算法图的拓扑排序Java开发Java经验技巧共6页.p

    对于给定的"本周算法图的拓扑排序Java开发Java经验技巧共6页.pdf.zip"文件,很可能是包含了一篇关于拓扑排序在Java编程实践中的详细教程或指南,内容可能包括理论解释、代码示例、常见问题以及优化技巧。通过阅读这...

    拓扑排序应用系统java.zip

    拓扑排序是图论中的一个重要概念,特别是在有向无环图(DAG,Directed Acyclic Graph)中。在计算机科学中,它常被用于解决依赖关系的排序问题,例如任务调度、编译器的语句生成等。在这个“拓扑排序应用系统java....

    Java版查找并打印有向图中的所有环路径

    另一方面,拓扑排序是将有向无环图(DAG)的顶点线性排列的一种方式,如果存在环,则无法进行拓扑排序,因此可以借此判断图中是否有环。 在`Graph.java`中,可能会有一个名为`detectCycle`的函数,它使用DFS进行...

    基于拓扑排序的排课程序

    1. **深度优先搜索(DFS)**或**广度优先搜索(BFS)**:这两种算法都可以用于实现拓扑排序。DFS通常会产生一个深浅不一的排序,而BFS则会得到一个较为均匀的排序结果。在排课场景中,BFS可能更为合适,因为它可以...

    java深度优先遍历

    - 拓扑排序:在有向无环图(DAG)中,DFS可以用于拓扑排序,确定节点的顺序。 5. **代码示例**: 在Java中,使用递归实现二叉树的DFS遍历(前序、中序、后序)如下: ```java class TreeNode { int val; ...

    数据结构拓扑排序图形化界面实现

    在有环的有向图上执行拓扑排序是不定义的,因此程序应检测到环并给出适当的错误提示。 6. **可视化**:为了让用户直观看到拓扑排序的过程,可以使用动画效果,动态展示节点的移动和排序顺序。这需要在GUI中集成动画...

    Java实现图的深度优先遍历和广度优先遍历

    图的深度优先遍历和广度优先遍历是探索图结构的两种基本方法,它们各有优势。DFS适合查找路径或进行拓扑排序,而BFS则更适合寻找最短路径或检查连通性。在Java中,通过适当的递归或迭代算法结合数据结构(如栈或队列...

    20180729数据结构与算法基础班深度优先搜索

    深度优先搜索(DFS,Depth-First Search)是图论与数据结构中的一种经典搜索算法,广泛应用于解决实际问题,如网络爬虫、迷宫求解、拓扑排序等。本课程“20180729数据结构与算法基础班深度优先搜索”将深入探讨这一...

    java 深度优先遍历、广度优先遍历、最短路径、最小生成树

    本文将深入探讨Java中实现的四个核心图算法:深度优先遍历(DFS)、广度优先遍历(BFS)、最短路径算法以及最小生成树算法。 首先,**深度优先遍历(DFS)**是一种用于遍历或搜索树或图的算法。它从根节点开始,尽...

    蓝桥杯深度优先搜索

    深度优先搜索(Depth-First Search, DFS)是一种用于遍历或搜索树或图的算法,它的基本思想是尽可能深地探索图的分支。在遇到死胡同时,算法会回溯到上一步,尝试其他可能的路径。DFS在解决许多算法问题中发挥着重要...

    Graph-DFS_WFS.zip_java无向图_wfs遍历_深度优先遍历

    在IT领域,图遍历是数据结构和算法中一个重要的概念,主要应用于网络拓扑排序、搜索路径等问题。本文将详细讲解"Graph-DFS_WFS.zip"压缩包中涉及的知识点,包括Java实现的无向图、深度优先遍历(DFS)以及宽度优先...

    深度优先搜索学习五例之一(JAVA)

    3. **拓扑排序**:在有向无环图(DAG)中,DFS可以用来进行拓扑排序,将所有节点按照没有前驱的顺序排列。 4. **迷宫求解**:DFS也可以应用于二维数组表示的迷宫问题,从起点开始,不断尝试所有可能的路径,直到找到...

    java 图 邻接表 深度优先遍历 广度优先遍历 最短路径

    用Java描述的图,以邻接表存储,包含常用算法

    Putuo-Sort.rar_拓扑排序

    拓扑排序是图论中的一个重要概念,特别是在有向无环图(DAG,Directed Acyclic Graph)中。在这个课程设计报告中,我们将深入探讨拓扑排序的原理、应用及其实现过程。 一、程序分析 1)输入需求:拓扑排序算法通常...

    java深度优先搜索 可以设置图的一系列数据

    总的来说,Java中的深度优先搜索可以通过栈或递归来实现,用于遍历图或树结构的所有节点。理解并熟练掌握DFS对于解决许多图论问题至关重要,例如寻找连通分量、判断有向图是否存在环、求解最短路径等。在实际应用中...

Global site tag (gtag.js) - Google Analytics