zoukankan      html  css  js  c++  java
  • 有向图(拓扑排序算法)

         对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若<u,v> ∈E(G),则u在线性序列中出现在v之前。
         通常,这样的线性序列称为满足拓扑次序(TopoiSicai Order)的序列,简称拓扑序列
      注意:
         ①若将图中顶点按拓扑次序排成一行,则图中所有的有向边均是从左指向右的。
         ②若图中存在有向环,则不可能使顶点满足拓扑次序。
         ③一个DAG的拓扑序列通常表示某种方案切实可行。

    下面是Java实现:

      1 package zieckey.datastructure.study.graph;
      2 
      3 /**
      4  * 有方向图
      5  *
      6  * @author zieckey
      7  */
      8 public class DirectedGraph
      9 {
     10     private final int    MAX_VERTS    = 20;
     11     private Vertex[]    vertexList;        // array of vertices
     12 
     13     private int[][]        adjMat;            // adjacency matrix
     14 
     15     private int            nVerts;            // current number of vertices
     16 
     17     private char[]        sortedArray;        // sorted vert labels
     18 
     19 
     20     /**
     21      * 默认构造函数 初始化邻接矩阵
     22      */
     23     public DirectedGraph( )
     24     {
     25         vertexList = new Vertex[MAX_VERTS];
     26         sortedArray = new char[MAX_VERTS];
     27         // 图的邻接矩阵adjacency matrix
     28 
     29         adjMat = new int[MAX_VERTS][MAX_VERTS];
     30         nVerts = 0;
     31         for ( int j = 0; j < MAX_VERTS; j++ )
     32         {
     33             // set adjacency
     34 
     35             for ( int k = 0; k < MAX_VERTS; k++ )
     36             {
     37                 adjMat[j][k] = 0;
     38             }
     39         }
     40     }
     41     
     42     /**
     43      * 对有向图进行拓扑排序
     44      *
     45      * 无后继的顶点优先拓扑排序方法
     46      * 1、思想方法
     47      * 该方法的每一步均是输出当前无后继(即出度为0)的顶点。
     48      * 对于一个DAG,按此方法输出的序列是逆拓扑次序。
     49      * 因此设置一个栈(或向量)T来保存输出的顶点序列,即可得到拓扑序列。
     50      * 若T是栈,则每当输出顶点时,只需做人栈操作,排序完成时将栈中顶点依次出栈即可得拓扑序列。
     51      * 若T是向量,则将输出的顶点从T[n-1]开始依次从后往前存放,即可保证T中存储的顶点是拓扑序列。
     52      */
     53     public void nonSuccFirstToplogicalSort()
     54     {
     55         int orig_nVerts = nVerts;
     56         while(nVerts>0)
     57         {
     58             int delVertex = getNoSuccessorVertex();
     59             if ( -1 == delVertex )
     60             {
     61                 System.out.println("Error: This graph has cycles! It cannot be toplogical sorted.");
     62                 return;
     63             }
     64             
     65             sortedArray[nVerts-1= vertexList[delVertex].label;
     66             deleteVertex( delVertex );
     67         }
     68         
     69         System.out.print("Topologically sorted order: ");
     70         for(int j=0; j<orig_nVerts; j++)
     71         {
     72             System.out.print( sortedArray[j] );
     73         }
     74         System.out.println("");
     75     }
     76     
     77     /**
     78      * 找到没有后继节点的节点
     79      * @return
     80      */
     81     public int getNoSuccessorVertex()
     82     {
     83         boolean isEdge;
     84         for ( int row = 0; row < nVerts; row++ )
     85         {
     86             isEdge = false;
     87             for ( int column = 0; column < nVerts; column++ )
     88             {
     89                 if ( adjMat[row][column]>0 )//大于0,表明有边指向其他点,说明有后继节点
     90 
     91                 {    
     92                     isEdge = true;
     93                     break;                    //OK,继续下一个节点
     94 
     95                 }
     96             }
     97             
     98             if ( false == isEdge )//没有边,表明没有后继节点
     99 
    100             {
    101                 return row;
    102             }
    103         }
    104         return -1;
    105     }
    106     
    107     /**
    108      * 删除一个节点
    109      * @param delVertex
    110      */
    111     public void deleteVertex( int delVertex )
    112     {
    113         if ( delVertex != nVerts-1 )//如果不是最后一个节点
    114 
    115         {
    116             //在节点列表中删除这个节点,所有后面的节点前移一格
    117 
    118             for ( int i = delVertex; i < nVerts-1; i++ )
    119             {
    120                 vertexList[i] = vertexList[i+1];
    121             }
    122             
    123             // 删除邻接矩阵的delVertex行和列,即所有后面的行和列都向前移动一格
    124 
    125             // 所有delVertex行后的行,向上一个格
    126 
    127             for ( int row = delVertex; row < nVerts - 1; row++ )
    128             {
    129                 for ( int column = 0; column < nVerts; column++ )
    130                 {
    131                     adjMat[row][column] = adjMat[row + 1][column];
    132                 }
    133             }
    134             
    135             // 所有delVertex列后的列,向左一个格
    136 
    137             for ( int column = delVertex; column < nVerts; column++ )
    138             {
    139                 for ( int row = 0; row < nVerts - 1; row++ )                
    140                 {
    141                     adjMat[row][column] = adjMat[row][column+1];
    142                 }
    143             }
    144         }
    145         
    146         nVerts--;//减少一个节点
    147 
    148     }
    149     
    150     /**
    151      * 添加一个节点
    152      *
    153      * @param lab
    154      */
    155     public void addVertex( char lab ) // argument is label
    156 
    157     {
    158         vertexList[nVerts++ ] = new Vertex( lab );
    159     }
    160 
    161     /**
    162      * 添加一条边
    163      *
    164      * @param start
    165      * 起始点
    166      * @param end
    167      * 终点
    168      */
    169     public void addEdge( int start, int end )
    170     {
    171         adjMat[start][end] = 1;
    172     }
    173 
    174     /**
    175      * 添加一条边
    176      *
    177      * @param start
    178      * 起始点
    179      * @param end
    180      * 终点
    181      */
    182     public void addEdge( char startVertex, char endVertex )
    183     {
    184         int start = getIndexByLabel( startVertex );
    185         int end = getIndexByLabel( endVertex );
    186         if ( -1 != start && -1 != end )
    187         {
    188             adjMat[start][end] = 1;
    189         }
    190     }
    191     
    192     /**
    193      * 显示一个节点
    194      *
    195      * @param v
    196      */
    197     public void displayVertex( int v )
    198     {
    199         System.out.print( vertexList[v].label );
    200     }
    201 
    202     public int getIndexByLabel( char lable )
    203     {
    204         for ( int i = 0; i < vertexList.length; i++ )
    205         {
    206             if ( lable == vertexList[i].label )
    207             {
    208                 return i;
    209             }
    210         }
    211 
    212         // 没有这个节点
    213 
    214         return -1;
    215     }
    216 }

  • 相关阅读:
    进击的实时数仓:Flink 在 OPPO 实时计算平台的研发与应用实践
    vue中将时间戳转换为YYYY-MM-dd hh:mm格式时间的组件
    vue 将时间戳转换成日期格式 (一)
    element-ui DatePicker 日期选择器 让结束日期大于开始日期
    css 边框上如何写入文字?
    2019最新Web前端经典面试试题(含答案)
    Nginx 安装及配置
    前端基础面试题(JS部分)
    const与指针
    linux配置-------redhat虚拟机的中文输入法配置
  • 原文地址:https://www.cnblogs.com/zack/p/1440167.html
Copyright © 2011-2022 走看看