zoukankan      html  css  js  c++  java
  • 拓扑排序

    对于一个有向无环图G=(V,E)来说,拓扑排序就是G中所有结点的一种线性次序,该次序满足如下条件:其结点u在拓扑排序中处于v的前面(如果图G包含环路,则不可能排出一个线性次序),可以将图的拓扑排序看作是将图的所有结点在一条水平线上展开,在该水平线上,所有的有向边都是从左向右。

    我们构造拓扑排序主要循环一下两步:

    1)选择一个入度为0的顶点并输出;

    2)从网中删除此顶点以及所有出边;

      循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,否则输出的顶点序列就是一种拓扑序列。

    以下图为例,来说明拓扑排序算法的执行过程

                              

        (1) 在(a)图中v0和v1的入度都为0,不妨选择v0并输出之,接着删去顶点v0及出边<0,2>,得到的结果如(b)图所示。

        (2) 在(b)图中只有一个入度为0的顶点v1,输出v1,接着删去v1和它的三条出边<1,2>,<1,3>和<1,4>,得到的结果如(c)图所示。

        (3) 在(c)图中v2和v4的入度都为0,不妨选择v2并输出之,接着删去v2及两条出边<2,3>和<2,5>,得到的结果如(d)图所示。

        (4) 在(d)图上依次输出顶点v3,v4和v5,并在每个顶点输出后删除该顶点及出边,操作都很简单,不再赘述。

    在拓扑排序算法中,需要用一个一维数组来保存各个顶点的入度值,recode[]

        顶点: 0    1    2    3    4    5

        入度: 0    0    2    2    1    3

    看网上有各种算法,有的用栈,有的用队列,但是我自己在里面嵌套了一个循环所有结点是否访问过,如果有没访问过的,即visited[i]==0,那么继续从头开始遍历点,这样做复杂度会高一些,但是比较容易理解。

    import java.util.LinkedList;
    import java.util.Queue;
    import java.util.Scanner;
    /*
     * 我们应该将焦点集中在入度上,当这个定点的所有入边对应的定点都被访问过,那么才能访问该节点
     */
    
    public class Test {
        static int edge,node;   //边数、顶点数
        static int [][]map=new int[20][20];
        static int [] visited=new int [20];
        static int [] recode=new int [20];   //记录入度
        static int [] recode1=new int [20];
        static Queue<Integer> q=new LinkedList<Integer>();
        static boolean falg;
        static Scanner sc=new Scanner(System.in);
        public static void main(String[] args) {
            int f,t;
            falg=false;
            edge=sc.nextInt();
            node=sc.nextInt();
            for(int i=0;i<=node;i++) {visited[i]=0;recode[i]=0;recode1[i]=0;}
            for(int i=1;i<=edge;i++){
                f=sc.nextInt();
                t=sc.nextInt();
                map[f][t]=1;     //代表从f->t存在边。
                recode[t]++;
            }
            while(falg!=true){
            for(int i=1;i<=node;i++){
                if(recode[i]==0&&visited[i]==0){
                    System.out.println(i);
                    visited[i]=1;
                    for(int j=1;j<=node;j++){
                        if(map[i][j]==1)  {map[i][j]=0;recode[j]--;}
                    }
                }
                int num=0;
                for(int j=1;j<=node;j++){
                    if(visited[j]==1) num++;
                }
                if(num==node)  falg=true;   //如果所有点都访问过,那么应该结束循环
            }
            }
        }
        
        
    }
  • 相关阅读:
    Oracle rownum用法、分页
    Oracle 序列(查询序列的值,修改序列的值)
    Photoshop 更换证件照底色
    Oracle 新建用户、赋予权限
    Oracle-SQL 建表
    SQL decode 函数的用法
    英语词汇800常用20类
    c语言常用排序
    js时间戳总结
    Javascript之编译器
  • 原文地址:https://www.cnblogs.com/wintersong/p/5033978.html
Copyright © 2011-2022 走看看