Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 2971|回复: 0

[算法学习]有向无环图的拓扑排序(深度优先搜索实现)java

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-12-6 00:07:20 | 显示全部楼层 |阅读模式
    当每个任务有前后置关系时,需要找到一种满足前后置关系的路线,将任务完成。    如果将每个任务看成一个节点,任务之间的前后置关系表示为有向图时,这种路线顺序叫做为图进行拓扑排序。也叫关键路径分析。  比如有很多任务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=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]





    1.                                   public enum VertexState {
    2.         UNVISITED,VISITED,PASSED;//未访问,已访问,已经过
    3. }
    4. import java.util.Set;
    5. import java.util.List;
    6. import java.util.HashSet;
    7. import java.util.ArrayList;
    8. import java.util.Collections;
    9. //顶点类
    10. class Vertex
    11.    {
    12.     private String label;        
    13.     private VertexState state;//顶点状态
    14.    public Vertex(String lab)   
    15.       {
    16.       label = lab;
    17.       state = VertexState.UNVISITED;
    18.       }

    19.    public VertexState getState(){
    20.          return state;
    21.    }
    22.    public void setState(VertexState state){
    23.          this.state=state;
    24.    }
    25.    public String toString(){
    26.        return label;
    27.    }
    28.    
    29.    }
    30. //有向图的邻接矩阵实现
    31. class Graph
    32.    {
    33.    private final int MAX_VERTS = 30;
    34.    private Vertex vertexList[]; // 存放顶点的数组
    35.    private int adjMat[][];      // 邻接矩阵
    36.    private int nVerts;          // 当前的顶点数

    37.    public Graph()            
    38.       {
    39.       vertexList = new Vertex[MAX_VERTS];
    40.                                          
    41.       adjMat = new int[MAX_VERTS][MAX_VERTS];
    42.       nVerts = 0;
    43.       for(int y=0; y< MAX_VERTS; y++)      
    44.          for(int x=0; x< MAX_VERTS; x++)   
    45.             adjMat[x][y] = 0;
    46.       
    47.       }  
    48.     public  void addVertex(Vertex v)//在图中添加一个顶点
    49.       {
    50.       vertexList[nVerts++] = v;
    51.       }
    52.   //在图中增加一条边,从start到end
    53.    public void addEdge(int start, int end)
    54.       {
    55.       adjMat[start][end] = 1;
    56.    
    57.       }
    58.        /**
    59.          * 返回v顶点所关联的邻结点
    60.          * @param v
    61.          * @return
    62.          */
    63.    private Set< Vertex> getNeighbors(Vertex v){
    64.                Set< Vertex> vSet = new HashSet< Vertex>();
    65.                int index=getIndex(v);
    66.                if(index==-1) return null;
    67.                for(int i=0;i< nVerts;i++)
    68.                   if(adjMat[index][i]==1)
    69.                       vSet.add(vertexList[i]);
    70.             
    71.                 return vSet;
    72.         }
    73.       
    74.        //返回顶点在vertexList数组中的索引
    75.      private int getIndex(Vertex v){
    76.           for(int i=0;i< nVerts;i++)
    77.             if(vertexList[i]==v)
    78.                 return i;
    79.            return -1;
    80.         }
    81.       /**
    82.          * 全部节点设为未访问
    83.          */
    84.     private void allUnVisted(){
    85.                 Vertex v=null;
    86.                 int len = nVerts;
    87.                 for(int i = 0; i < len ; i++){
    88.                         v = vertexList[i];
    89.                         if(v.getState() != VertexState.UNVISITED){
    90.                                 v.setState(VertexState.UNVISITED);
    91.                         }
    92.                 }
    93.         }
    94.     private boolean containsVertex(Vertex v){
    95.          int index=getIndex(v);
    96.          if(index!=-1) return true;
    97.          else return false;
    98.                
    99.                
    100.         }
    101.     private VertexState getState(Vertex v){
    102.                
    103.                 return v.getState();
    104.         }
    105.     private VertexState setState(Vertex v, VertexState state) {
    106.                
    107.                 VertexState preState = v.getState();
    108.                 v.setState(state);
    109.                 return preState;
    110.         }
    111.    /**
    112.          * 深度优先遍历一个顶点
    113.          * @param
    114.          * @param graph
    115.          * @param v
    116.          * @param checkCycle
    117.          * @return
    118.          */
    119.     public List< Vertex> dfs(Vertex v,boolean checkCycle){
    120.                 allUnVisted();
    121.                 List< Vertex> vList = new ArrayList< Vertex>();
    122.                 dfsHandler(v,checkCycle,vList);
    123.                 return vList;
    124.         }
    125.   
    126.       private void dfsHandler(Vertex v,boolean checkCycle,List< Vertex> vList){
    127.                   Set< Vertex> neighbors = null;
    128.                 if(!containsVertex(v)){
    129.                         throw new IllegalStateException("不存在该顶点");
    130.                 }
    131.                 setState(v, VertexState.PASSED);
    132.                
    133.                 neighbors = getNeighbors(v);
    134.                 VertexState state = null;
    135.                 for(Vertex neighbor : neighbors){
    136.                         state = getState(neighbor);
    137.                         if(state == VertexState.UNVISITED){//未遍历,
    138.                                //  System.out.println(neighbor+",");
    139.                                 dfsHandler(neighbor, checkCycle, vList);
    140.                         }else if(state == VertexState.PASSED && checkCycle){//
    141.                              
    142.                                 throw new IllegalStateException("存在一个环");
    143.                         }
    144.                 }
    145.                 setState(v, VertexState.VISITED);//访问结束设为已访问
    146.                 vList.add(v);
    147.                // System.out.println("++"+v);
    148.                
    149.         }
    150.     /**
    151.          * 图的拓扑排序
    152.          * @param
    153.          * @param graph
    154.          * @return
    155.          */
    156.         public List< Vertex> topo(){
    157.                 List< Vertex> vList = new ArrayList< Vertex>();
    158.                 allUnVisted();
    159.                 for(int i=0;i< nVerts;i++){
    160.                         if(getState(vertexList[i]) == VertexState.UNVISITED){
    161.                                 try{
    162.                                         dfsHandler(vertexList[i], true, vList);
    163.                                 }catch (IllegalStateException e) {
    164.                                         throw new IllegalStateException("图有一个环");
    165.                                 }
    166.                         }
    167.                 }
    168.                 Collections.reverse(vList);
    169.                 return vList;
    170.     }
    171. }
    172. public class DFSApp
    173.    {
    174.    public static void main(String[] args)
    175.       {
    176.       Graph theGraph = new Graph();
    177.       Vertex v1=new Vertex("c0");
    178.       Vertex v2=new Vertex("c1");
    179.       Vertex v3=new Vertex("c2");
    180.       Vertex v4=new Vertex("c3");
    181.       Vertex v5=new Vertex("c4");
    182.       Vertex v6=new Vertex("c5");
    183.       Vertex v7=new Vertex("c6");
    184.       Vertex v8=new Vertex("c7");
    185.       Vertex v9=new Vertex("c8");
    186.   
    187.    
    188.       theGraph.addVertex(v1);    // 0  
    189.       theGraph.addVertex(v2);    // 1
    190.       theGraph.addVertex(v3);    // 2
    191.       theGraph.addVertex(v4);    // 3
    192.       theGraph.addVertex(v5);    // 4
    193.       theGraph.addVertex(v6);    // 5  
    194.       theGraph.addVertex(v7);    // 6
    195.       theGraph.addVertex(v8);    // 7
    196.       theGraph.addVertex(v9);    // 8
    197.       theGraph.addEdge(0, 6);     // c0->c6
    198.       theGraph.addEdge(0, 2);     // c0->c2
    199.       theGraph.addEdge(3, 5);     // c3->c5
    200.       theGraph.addEdge(3, 8);     // c3->c8
    201.       theGraph.addEdge(1, 2);     // c1->c2
    202.       theGraph.addEdge(1, 4);     // c1->c4
    203.       theGraph.addEdge(2, 3);     // c2->c3
    204.       theGraph.addEdge(6, 7);     // c6->c7
    205.       theGraph.addEdge(7, 8);     // c7->c8
    206.       theGraph.addEdge(4, 3);     // c4->c3
    207.       theGraph.addEdge(4, 5);     // c4->c5
    208.       //theGraph.addEdge(3, 1);     // c4->c5
    209.       System.out.print("Visits: ");
    210.       List< Vertex> vl=theGraph.topo();   
    211.        // List< Vertex> vl=theGraph.dfs(v1,false);            
    212.       System.out.println(vl);
    213.       }  
    214.    }
    215.                                   
    复制代码


      
      
       
       

         
       

         
       
      
    复制代码

    源码下载:http://file.javaxxz.com/2014/12/6/000719875.rar
    回复

    使用道具 举报

    该用户从未签到

    发表于 2015-1-2 15:45:04 | 显示全部楼层
    顶顶顶顶顶顶顶顶顶顶
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-25 14:33 , Processed in 0.403519 second(s), 34 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表